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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/.OwlBot.lock.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@
# limitations under the License.
docker:
image: gcr.io/cloud-devrel-public-resources/owlbot-python:latest
digest: sha256:25de45b58e52021d3a24a6273964371a97a4efeefe6ad3845a64e697c63b6447
# created: 2025-04-14T14:34:43.260858345Z
digest: sha256:4a9e5d44b98e8672e2037ee22bc6b4f8e844a2d75fcb78ea8a4b38510112abc6
# created: 2025-10-07
6 changes: 3 additions & 3 deletions .github/sync-repo-settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,18 @@ branchProtectionRules:
# List of required status check contexts that must pass for commits to be accepted to matching branches.
requiredStatusCheckContexts:
- 'Kokoro'
- 'Kokoro system-3.7'
- 'Kokoro system'
- 'cla/google'
- 'OwlBot Post Processor'
- 'docs'
- 'docfx'
- 'lint'
- 'unit (3.7)'
- 'unit (3.8)'
- 'unit (3.9)'
- 'unit (3.10)'
- 'unit (3.11)'
- 'unit (3.12)'
- 'unit (3.13)'
- 'unit (3.14)'
- 'cover'
- 'run-systests'
# List of explicit permissions to add (additive only)
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.8"
python-version: "3.13"
- name: Install nox
run: |
python -m pip install --upgrade setuptools pip wheel
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/mypy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.8"
python-version: "3.13"
- name: Install nox
run: |
python -m pip install --upgrade setuptools pip wheel
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/system_emulated.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.7'
python-version: '3.13'

# firestore emulator requires java 21+
- name: Setup Java
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/unittest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-22.04
strategy:
matrix:
python: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12', '3.13']
python: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12', '3.13', '3.14']
steps:
- name: Checkout
uses: actions/checkout@v4
Expand Down Expand Up @@ -45,7 +45,7 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.8"
python-version: "3.13"
- name: Install coverage
run: |
python -m pip install --upgrade setuptools pip wheel
Expand Down
7 changes: 7 additions & 0 deletions .kokoro/presubmit/system-3.14.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Format: //devtools/kokoro/config/proto/build.proto

# Only run this nox session.
env_vars: {
key: "NOX_SESSION"
value: "system-3.14"
}
7 changes: 7 additions & 0 deletions .kokoro/presubmit/system-3.9.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Format: //devtools/kokoro/config/proto/build.proto

# Only run this nox session.
env_vars: {
key: "NOX_SESSION"
value: "system-3.9"
}
7 changes: 7 additions & 0 deletions .kokoro/presubmit/system.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Format: //devtools/kokoro/config/proto/build.proto

# Only run this nox session.
env_vars: {
key: "NOX_SESSION"
value: "system-3.9"
}
7 changes: 4 additions & 3 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ In order to add a feature:
documentation.

- The feature must work fully on the following CPython versions:
3.7, 3.8, 3.9, 3.10, 3.11, 3.12 and 3.13 on both UNIX and Windows.
3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13 and 3.14 on both UNIX and Windows.

- The feature must not add unnecessary dependencies (where
"unnecessary" is of course subjective, but new dependencies should
Expand Down Expand Up @@ -72,7 +72,7 @@ We use `nox <https://nox.readthedocs.io/en/latest/>`__ to instrument our tests.

- To run a single unit test::

$ nox -s unit-3.13 -- -k <name of test>
$ nox -s unit-3.14 -- -k <name of test>


.. note::
Expand Down Expand Up @@ -238,14 +238,15 @@ We support:
- `Python 3.11`_
- `Python 3.12`_
- `Python 3.13`_
- `Python 3.14`_

.. _Python 3.7: https://docs.python.org/3.7/
.. _Python 3.8: https://docs.python.org/3.8/
.. _Python 3.9: https://docs.python.org/3.9/
.. _Python 3.10: https://docs.python.org/3.10/
.. _Python 3.11: https://docs.python.org/3.11/
.. _Python 3.12: https://docs.python.org/3.12/
.. _Python 3.13: https://docs.python.org/3.13/
.. _Python 3.14: https://docs.python.org/3.14/


Supported versions can be found in our ``noxfile.py`` `config`_.
Expand Down
3 changes: 2 additions & 1 deletion google/cloud/firestore_bundle/bundle.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,9 +344,10 @@ def build(self) -> str:
BundleElement(document_metadata=bundled_document.metadata)
)
document_count += 1
bundle_pb = bundled_document.snapshot._to_protobuf()
buffer += self._compile_bundle_element(
BundleElement(
document=bundled_document.snapshot._to_protobuf()._pb,
document=bundle_pb._pb if bundle_pb else None,
)
)

Expand Down
10 changes: 6 additions & 4 deletions google/cloud/firestore_v1/async_transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@
AsyncGenerator,
Awaitable,
Callable,
Generic,
Optional,
)
from typing_extensions import Concatenate, ParamSpec, TypeVar

from google.api_core import exceptions, gapic_v1
from google.api_core import retry_async as retries
Expand All @@ -44,14 +46,14 @@
# Types needed only for Type Hints
if TYPE_CHECKING: # pragma: NO COVER
import datetime
from typing_extensions import TypeVar, ParamSpec, Concatenate

from google.cloud.firestore_v1.async_stream_generator import AsyncStreamGenerator
from google.cloud.firestore_v1.base_document import DocumentSnapshot
from google.cloud.firestore_v1.query_profile import ExplainOptions

T = TypeVar("T")
P = ParamSpec("P")

T = TypeVar("T")
P = ParamSpec("P")


class AsyncTransaction(async_batch.AsyncWriteBatch, BaseTransaction):
Expand Down Expand Up @@ -253,7 +255,7 @@ async def get(
)


class _AsyncTransactional(_BaseTransactional):
class _AsyncTransactional(_BaseTransactional, Generic[T, P]):
"""Provide a callable object to use as a transactional decorater.

This is surfaced via
Expand Down
2 changes: 1 addition & 1 deletion google/cloud/firestore_v1/base_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -929,7 +929,7 @@ def _normalize_cursor(self, cursor, orders) -> Tuple[List, bool] | None:

if isinstance(document_fields, document.DocumentSnapshot):
snapshot = document_fields
document_fields = snapshot.to_dict()
document_fields = copy.deepcopy(snapshot._data)
document_fields["__name__"] = snapshot.reference

if isinstance(document_fields, dict):
Expand Down
6 changes: 5 additions & 1 deletion mypy.ini
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
[mypy]
python_version = 3.8
python_version = 3.13
namespace_packages = True

# ignore gapic files
[mypy-google.cloud.firestore_v1.services.*]
ignore_errors = True
28 changes: 21 additions & 7 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
ISORT_VERSION = "isort==5.11.0"
LINT_PATHS = ["docs", "google", "tests", "noxfile.py", "setup.py"]

DEFAULT_PYTHON_VERSION = "3.8"
DEFAULT_PYTHON_VERSION = "3.13"

UNIT_TEST_PYTHON_VERSIONS: List[str] = [
"3.7",
Expand All @@ -43,6 +43,7 @@
"3.11",
"3.12",
"3.13",
"3.14",
]
UNIT_TEST_STANDARD_DEPENDENCIES = [
"mock",
Expand All @@ -61,7 +62,7 @@
UNIT_TEST_EXTRAS: List[str] = []
UNIT_TEST_EXTRAS_BY_PYTHON: Dict[str, List[str]] = {}

SYSTEM_TEST_PYTHON_VERSIONS: List[str] = ["3.7"]
SYSTEM_TEST_PYTHON_VERSIONS: List[str] = ["3.9", "3.14"]
SYSTEM_TEST_STANDARD_DEPENDENCIES: List[str] = [
"mock",
"pytest",
Expand All @@ -79,7 +80,12 @@
CURRENT_DIRECTORY = pathlib.Path(__file__).parent.absolute()

nox.options.sessions = [
"unit",
"unit-3.9",
"unit-3.10",
"unit-3.11",
"unit-3.12",
"unit-3.13",
"unit-3.14",
"system_emulated",
"system",
"mypy",
Expand Down Expand Up @@ -170,7 +176,7 @@ def mypy(session):
@nox.session(python=DEFAULT_PYTHON_VERSION)
def lint_setup_py(session):
"""Verify that setup.py is valid (including RST check)."""
session.install("docutils", "pygments")
session.install("setuptools", "docutils", "pygments")
session.run("python", "setup.py", "check", "--restructuredtext", "--strict")


Expand Down Expand Up @@ -210,7 +216,8 @@ def install_unittest_dependencies(session, *constraints):
def unit(session, protobuf_implementation):
# Install all test dependencies, then install this package in-place.

if protobuf_implementation == "cpp" and session.python in ("3.11", "3.12", "3.13"):
py_version = tuple([int(v) for v in session.python.split(".")])
if protobuf_implementation == "cpp" and py_version >= (3, 11):
session.skip("cpp implementation is not supported in python 3.11+")

constraints_path = str(
Expand Down Expand Up @@ -375,7 +382,13 @@ def cover(session):
test runs (not system test runs), and then erases coverage data.
"""
session.install("coverage", "pytest-cov")
session.run("coverage", "report", "--show-missing", "--fail-under=100")
session.run(
"coverage",
"report",
"--show-missing",
"--fail-under=100",
"--omit=tests/*",
)

session.run("coverage", "erase")

Expand Down Expand Up @@ -469,7 +482,8 @@ def docfx(session):
def prerelease_deps(session, protobuf_implementation):
"""Run all tests with prerelease versions of dependencies installed."""

if protobuf_implementation == "cpp" and session.python in ("3.11", "3.12", "3.13"):
py_version = tuple([int(v) for v in session.python.split(".")])
if protobuf_implementation == "cpp" and py_version >= (3, 11):
session.skip("cpp implementation is not supported in python 3.11+")

# Install all dependencies
Expand Down
4 changes: 3 additions & 1 deletion owlbot.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,12 +138,14 @@ def update_fixup_scripts(library):
# ----------------------------------------------------------------------------
templated_files = common.py_library(
samples=False, # set to True only if there are samples
system_test_python_versions=["3.7"],
unit_test_external_dependencies=["aiounittest", "six", "freezegun"],
system_test_external_dependencies=["pytest-asyncio", "six"],
microgenerator=True,
cov_level=100,
split_system_tests=True,
default_python_version="3.13",
system_test_python_versions=["3.9", "3.14"],
unit_test_python_versions=["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"],
)

s.move(templated_files,
Expand Down
5 changes: 5 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,8 @@ filterwarnings =
ignore:After January 1, 2024, new releases of this library will drop support for Python 3.7:DeprecationWarning
# Remove warning once https://github.com/googleapis/gapic-generator-python/issues/1939 is fixed
ignore:get_mtls_endpoint_and_cert_source is deprecated.:DeprecationWarning
# Remove once credential file support is removed
ignore:.*The \`credentials_file\` argument is deprecated.*:DeprecationWarning
# Remove after updating test dependencies that use asyncio.iscoroutinefunction
ignore:.*\'asyncio.iscoroutinefunction\' is deprecated.*:DeprecationWarning
ignore:.*\'asyncio.get_event_loop_policy\' is deprecated.*:DeprecationWarning
2 changes: 2 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Operating System :: OS Independent",
"Topic :: Internet",
"Topic :: Software Development :: Libraries :: Python Modules",
Expand Down
Empty file added testing/constraints-3.14.txt
Empty file.
13 changes: 13 additions & 0 deletions tests/unit/v1/test_base_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -1400,6 +1400,19 @@ def test_basequery__normalize_cursor_as_snapshot_hit():
assert query._normalize_cursor(cursor, query._orders) == ([1], True)


def test_basequery__normalize_cursor_non_existant_snapshot():
from google.cloud.firestore_v1 import document

values = {"b": 1}
docref = _make_docref("here", "doc_id")
snapshot = document.DocumentSnapshot(docref, values, False, None, None, None)
cursor = (snapshot, True)
collection = _make_collection("here")
query = _make_base_query(collection).order_by("b", "ASCENDING")

assert query._normalize_cursor(cursor, query._orders) == ([1], True)


def test_basequery__normalize_cursor_w___name___w_reference():
db_string = "projects/my-project/database/(default)"
client = mock.Mock(spec=["_database_string"])
Expand Down
Loading