Skip to content

Commit

Permalink
Merge branch 'main' into fix-compressed_repeated_to_uncompressed_prop…
Browse files Browse the repository at this point in the history
…erty
  • Loading branch information
zyzniewski committed Jan 29, 2023
2 parents a2d6fa3 + 3f0e236 commit 1ff11d2
Show file tree
Hide file tree
Showing 44 changed files with 210 additions and 211 deletions.
1 change: 0 additions & 1 deletion .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ show_missing = True
exclude_lines =
# Re-enable the standard pragma
pragma: NO COVER
pragma: NO PY${PY_VERSION} COVER
omit =
*/gapic/*.py
*/proto/*.py
Expand Down
4 changes: 2 additions & 2 deletions .github/.OwlBot.lock.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2022 Google LLC
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -13,4 +13,4 @@
# limitations under the License.
docker:
image: gcr.io/cloud-devrel-public-resources/owlbot-python:latest
digest: sha256:3bf87e47c2173d7eed42714589dc4da2c07c3268610f1e47f8e1a30decbfc7f1
digest: sha256:c43f1d918bcf817d337aa29ff833439494a158a0831508fda4ec75dc4c0d0320
2 changes: 1 addition & 1 deletion .kokoro/noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def get_pytest_env_vars() -> Dict[str, str]:

# DO NOT EDIT - automatically generated.
# All versions used to test samples.
ALL_VERSIONS = ["3.7", "3.8", "3.9", "3.10"]
ALL_VERSIONS = ["3.7", "3.8", "3.9", "3.10", "3.11"]

# Any default versions that should be ignored.
IGNORED_VERSIONS = TEST_CONFIG["ignored_versions"]
Expand Down
40 changes: 40 additions & 0 deletions .kokoro/samples/python3.11/common.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Format: //devtools/kokoro/config/proto/build.proto

# Build logs will be here
action {
define_artifacts {
regex: "**/*sponge_log.xml"
}
}

# Specify which tests to run
env_vars: {
key: "RUN_TESTS_SESSION"
value: "py-3.11"
}

# Declare build specific Cloud project.
env_vars: {
key: "BUILD_SPECIFIC_GCLOUD_PROJECT"
value: "python-docs-samples-tests-311"
}

env_vars: {
key: "TRAMPOLINE_BUILD_FILE"
value: "github/python-ndb/.kokoro/test-samples.sh"
}

# Configure the docker image for kokoro-trampoline.
env_vars: {
key: "TRAMPOLINE_IMAGE"
value: "gcr.io/cloud-devrel-kokoro-resources/python-samples-testing-docker"
}

# Download secrets for samples
gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/python-docs-samples"

# Download trampoline resources.
gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline"

# Use the trampoline script to run in docker.
build_file: "python-ndb/.kokoro/trampoline_v2.sh"
6 changes: 6 additions & 0 deletions .kokoro/samples/python3.11/continuous.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Format: //devtools/kokoro/config/proto/build.proto

env_vars: {
key: "INSTALL_LIBRARY_FROM_SOURCE"
value: "True"
}
11 changes: 11 additions & 0 deletions .kokoro/samples/python3.11/periodic-head.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Format: //devtools/kokoro/config/proto/build.proto

env_vars: {
key: "INSTALL_LIBRARY_FROM_SOURCE"
value: "True"
}

env_vars: {
key: "TRAMPOLINE_BUILD_FILE"
value: "github/python-ndb/.kokoro/test-samples-against-head.sh"
}
6 changes: 6 additions & 0 deletions .kokoro/samples/python3.11/periodic.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Format: //devtools/kokoro/config/proto/build.proto

env_vars: {
key: "INSTALL_LIBRARY_FROM_SOURCE"
value: "False"
}
6 changes: 6 additions & 0 deletions .kokoro/samples/python3.11/presubmit.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Format: //devtools/kokoro/config/proto/build.proto

env_vars: {
key: "INSTALL_LIBRARY_FROM_SOURCE"
value: "True"
}
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@

[1]: https://pypi.org/project/google-cloud-ndb/#history

## [2.1.0](https://github.com/googleapis/python-ndb/compare/v2.0.0...v2.1.0) (2022-12-15)


### Features

* Support client_options for clients ([#815](https://github.com/googleapis/python-ndb/issues/815)) ([6f94f40](https://github.com/googleapis/python-ndb/commit/6f94f40dfcd6f10e3cec979e4eb2b83408c66a30))


### Bug Fixes

* **zlib:** Accomodate different Zlib compression levels ([#852](https://github.com/googleapis/python-ndb/issues/852)) ([c1ab83b](https://github.com/googleapis/python-ndb/commit/c1ab83b9581b3d4d10dc7d2508b1c93b14e3c31a))

## [2.0.0](https://github.com/googleapis/python-ndb/compare/v1.12.0...v2.0.0) (2022-12-06)


Expand Down
6 changes: 1 addition & 5 deletions google/cloud/ndb/_eventloop.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,7 @@
import uuid
import time

# Python 2.7 module name change
try:
import queue
except ImportError: # pragma: NO PY3 COVER
import Queue as queue
import queue

from google.cloud.ndb import utils

Expand Down
16 changes: 3 additions & 13 deletions google/cloud/ndb/_legacy_protocol_buffer.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,7 @@


# Python 3 doesn't have "long" anymore
try:
long(42)
except NameError: # pragma: NO PY2 COVER
long = int
long = int


class ProtocolBufferDecodeError(Exception):
Expand All @@ -31,10 +28,7 @@ class ProtocolBufferDecodeError(Exception):
class ProtocolMessage:
def MergePartialFromString(self, s):
a = array.array("B")
try:
a.frombytes(s)
except AttributeError: # pragma: NO PY3 COVER
a.fromstring(s)
a.frombytes(s)
d = Decoder(a, 0, len(a))
self.TryMerge(d)

Expand Down Expand Up @@ -204,11 +198,7 @@ def getPrefixedString(self):
raise ProtocolBufferDecodeError("truncated")
r = self.buf[self.idx : self.idx + length] # noqa: E203
self.idx += length
try:
prefixed = r.tobytes()
except AttributeError: # pragma: NO PY3 COVER
prefixed = r.tostring()
return prefixed
return r.tobytes()


__all__ = [
Expand Down
31 changes: 28 additions & 3 deletions google/cloud/ndb/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import os
import requests

import google.api_core.client_options

from google.api_core.gapic_v1 import client_info
from google.cloud import environment_vars
from google.cloud import _helpers
Expand Down Expand Up @@ -76,6 +78,9 @@ class Client(google_client.ClientWithProject):
The NDB client must be created in order to use NDB, and any use of NDB must
be within the context of a call to :meth:`context`.
The Datastore Emulator is used for the client if and only if the
DATASTORE_EMULATOR_HOST environment variable is set.
Arguments:
project (Optional[str]): The project to pass to proxied API methods. If
not passed, falls back to the default inferred from the
Expand All @@ -84,21 +89,38 @@ class Client(google_client.ClientWithProject):
credentials (Optional[:class:`~google.auth.credentials.Credentials`]):
The OAuth2 Credentials to use for this client. If not passed, falls
back to the default inferred from the environment.
client_options (Optional[:class:`~google.api_core.client_options.ClientOptions` or :class:`dict`])
Client options used to set user options on the client.
API Endpoint should be set through client_options.
"""

SCOPE = ("https://www.googleapis.com/auth/datastore",)
"""The scopes required for authenticating as a Cloud Datastore consumer."""

def __init__(self, project=None, namespace=None, credentials=None):
def __init__(
self, project=None, namespace=None, credentials=None, client_options=None
):
self.namespace = namespace
self.host = os.environ.get(environment_vars.GCD_HOST, DATASTORE_API_HOST)
self.client_info = _CLIENT_INFO
self._client_options = client_options

# Use insecure connection when using Datastore Emulator, otherwise
# use secure connection
emulator = bool(os.environ.get(environment_vars.GCD_HOST))
self.secure = not emulator

# Use Datastore API host from client_options if provided, otherwise use default
api_endpoint = DATASTORE_API_HOST
if client_options is not None:
if type(client_options) == dict:
client_options = google.api_core.client_options.from_dict(
client_options
)
if client_options.api_endpoint:
api_endpoint = client_options.api_endpoint

self.host = os.environ.get(environment_vars.GCD_HOST, api_endpoint)

if emulator:
# When using the emulator, in theory, the client shouldn't need to
# call home to authenticate, as you don't need to authenticate to
Expand All @@ -108,10 +130,13 @@ def __init__(self, project=None, namespace=None, credentials=None):
super(Client, self).__init__(
project=project,
credentials=credentials,
client_options=client_options,
_http=requests.Session,
)
else:
super(Client, self).__init__(project=project, credentials=credentials)
super(Client, self).__init__(
project=project, credentials=credentials, client_options=client_options
)

if emulator:
channel = grpc.insecure_channel(self.host)
Expand Down
52 changes: 20 additions & 32 deletions google/cloud/ndb/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import collections
import contextlib
import contextvars
import itertools
import os
import six
Expand Down Expand Up @@ -60,43 +61,30 @@ def __next__(self):
_context_ids = _ContextIds()


try: # pragma: NO PY2 COVER
import contextvars
class _LocalState:
"""Thread local state."""

class _LocalState:
"""Thread local state."""

def __init__(self):
self._toplevel_context = contextvars.ContextVar(
"_toplevel_context", default=None
)
self._context = contextvars.ContextVar("_context", default=None)

@property
def context(self):
return self._context.get()

@context.setter
def context(self, value):
self._context.set(value)

@property
def toplevel_context(self):
return self._toplevel_context.get()

@toplevel_context.setter
def toplevel_context(self, value):
self._toplevel_context.set(value)
def __init__(self):
self._toplevel_context = contextvars.ContextVar(
"_toplevel_context", default=None
)
self._context = contextvars.ContextVar("_context", default=None)

@property
def context(self):
return self._context.get()

except ImportError: # pragma: NO PY3 COVER
@context.setter
def context(self, value):
self._context.set(value)

class _LocalState(threading.local):
"""Thread local state."""
@property
def toplevel_context(self):
return self._toplevel_context.get()

def __init__(self):
self.context = None
self.toplevel_context = None
@toplevel_context.setter
def toplevel_context(self, value):
self._toplevel_context.set(value)


_state = _LocalState()
Expand Down
2 changes: 1 addition & 1 deletion google/cloud/ndb/key.py
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ def __getnewargs__(self):
state to pickle. The dictionary has three keys ``pairs``, ``app``
and ``namespace``.
"""
return ( # pragma: NO PY2 COVER
return (
{
"pairs": self.pairs(),
"app": self.app(),
Expand Down
16 changes: 6 additions & 10 deletions google/cloud/ndb/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,11 +349,7 @@ class Person(Model):
GeoPt = helpers.GeoPoint
Rollback = exceptions.Rollback


try:
_getfullargspec = inspect.getfullargspec
except AttributeError: # pragma: NO PY3 COVER
_getfullargspec = inspect.getargspec
_getfullargspec = inspect.getfullargspec


class KindError(exceptions.BadValueError):
Expand Down Expand Up @@ -3068,9 +3064,9 @@ def _from_base_type(self, value):
Returns:
Any: The unpickled ``value``.
"""
if six.PY3 and type(value) is bytes: # pragma: NO BRANCH
return pickle.loads(value, encoding="bytes") # pragma: NO PY2 COVER
return pickle.loads(value) # pragma: NO PY3 COVER
if type(value) is bytes: # pragma: NO BRANCH
return pickle.loads(value, encoding="bytes")
return pickle.loads(value) # pragma: NO COVER


class JsonProperty(BlobProperty):
Expand Down Expand Up @@ -3317,7 +3313,7 @@ def __eq__(self, other):
return self._email == other._email and self._auth_domain == other._auth_domain

def __lt__(self, other):
if not isinstance(other, User): # pragma: NO PY2 COVER
if not isinstance(other, User):
return NotImplemented

return (self._email, self._auth_domain) < (
Expand Down Expand Up @@ -4911,7 +4907,7 @@ def __init__(_self, **kwargs):

def _get_property_for(self, p, indexed=True, depth=0):
"""Internal helper to get the Property for a protobuf-level property."""
if isinstance(p.name(), six.text_type): # pragma: NO PY2 COVER
if isinstance(p.name(), six.text_type):
p.set_name(bytes(p.name(), encoding="utf-8"))
parts = p.name().decode().split(".")
if len(parts) <= depth:
Expand Down

0 comments on commit 1ff11d2

Please sign in to comment.