Skip to content

Commit

Permalink
feat: Introduce compatibility with native namespace packages
Browse files Browse the repository at this point in the history
  • Loading branch information
parthea committed Nov 14, 2023
1 parent 00561f8 commit fdcceeb
Show file tree
Hide file tree
Showing 10 changed files with 68 additions and 81 deletions.
22 changes: 0 additions & 22 deletions google/__init__.py

This file was deleted.

22 changes: 0 additions & 22 deletions google/cloud/__init__.py

This file was deleted.

5 changes: 4 additions & 1 deletion google/cloud/sqlalchemy_spanner/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,7 @@

from .sqlalchemy_spanner import SpannerDialect

__all__ = (SpannerDialect,)
from .version import __version__


__all__ = (SpannerDialect, __version__)
5 changes: 2 additions & 3 deletions google/cloud/sqlalchemy_spanner/sqlalchemy_spanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import pkg_resources
import re

from alembic.ddl.base import (
Expand Down Expand Up @@ -45,6 +44,7 @@
from google.cloud.spanner_v1.data_types import JsonObject
from google.cloud import spanner_dbapi
from google.cloud.sqlalchemy_spanner._opentelemetry_tracing import trace_call
from google.cloud.sqlalchemy_spanner import __version__ as sqlalchemy_spanner_version
import sqlalchemy

USING_SQLACLCHEMY_20 = False
Expand Down Expand Up @@ -701,10 +701,9 @@ def create_connect_args(self, url):
),
url.database,
)
dist = pkg_resources.get_distribution("sqlalchemy-spanner")
return (
[match.group("instance"), match.group("database"), match.group("project")],
{"user_agent": f"gl-{dist.project_name}/{dist.version}"},
{"user_agent": f"gl-sqlalchemy-spanner/{sqlalchemy_spanner_version}"},
)

@engine_to_connection
Expand Down
File renamed without changes.
30 changes: 14 additions & 16 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import io
import os
import re
import setuptools


Expand All @@ -34,14 +35,17 @@
]
}

BASE_DIR = os.path.dirname(__file__)
VERSION_FILENAME = os.path.join(BASE_DIR, "version.py")
PACKAGE_INFO = {}
with open(VERSION_FILENAME) as f:
exec(f.read(), PACKAGE_INFO)
version = PACKAGE_INFO["__version__"]

package_root = os.path.abspath(os.path.dirname(__file__))

version = None

with open(
os.path.join(package_root, "google/cloud/sqlalchemy_spanner/version.py")
) as fp:
version_candidates = re.findall(r"(?<=\")\d+.\d+.\d+(?=\")", fp.read())
assert len(version_candidates) == 1
version = version_candidates[0]

readme_filename = os.path.join(package_root, "README.rst")
with io.open(readme_filename, encoding="utf-8") as readme_file:
readme = readme_file.read()
Expand All @@ -50,18 +54,13 @@
# benchmarks, etc.
packages = [
package
for package in setuptools.PEP420PackageFinder.find()
for package in setuptools.find_namespace_packages()
if package.startswith("google")
]

# Determine which namespaces are needed.
namespaces = ["google"]
if "google.cloud" in packages:
namespaces.append("google.cloud")

setuptools.setup(
author="Google LLC",
author_email="cloud-spanner-developers@googlegroups.com",
author_email="googleapis-packages@google.com",
classifiers=["Intended Audience :: Developers"],
description=description,
long_description=readme,
Expand All @@ -73,9 +72,8 @@
install_requires=dependencies,
extras_require=extras,
name=name,
namespace_packages=namespaces,
packages=packages,
url="https://github.com/cloudspannerecosystem/python-spanner-sqlalchemy",
url="https://github.com/googleapis/python-spanner-sqlalchemy",
version=version,
include_package_data=True,
zip_safe=False,
Expand Down
8 changes: 3 additions & 5 deletions test/test_suite_13.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import decimal
import operator
import os
import pkg_resources
import pytest
import random
import time
Expand Down Expand Up @@ -126,6 +125,8 @@
)
from test._helpers import get_db_url, get_project

from google.cloud.sqlalchemy_spanner import __version__ as sqlalchemy_spanner_version

config.test_schema = ""


Expand Down Expand Up @@ -1645,12 +1646,10 @@ class UserAgentTest(SpannerSpecificTestBase):
"""Check that SQLAlchemy dialect uses correct user agent."""

def test_user_agent(self):
dist = pkg_resources.get_distribution("sqlalchemy-spanner")

with self._engine.connect() as connection:
assert (
connection.connection.instance._client._client_info.user_agent
== f"gl-{dist.project_name}/{dist.version}"
== f"gl-sqlalchemy-spanner/{sqlalchemy_spanner_version}"
)


Expand Down Expand Up @@ -1702,7 +1701,6 @@ def setUp(self):

def test_offset_only(self):
for offset in [1, 7, 10, 100, 1000, 10000]:

with self._engine.connect().execution_options(read_only=True) as connection:
list(connection.execute(self._table.select().offset(offset)).fetchall())

Expand Down
9 changes: 4 additions & 5 deletions test/test_suite_14.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import decimal
import operator
import os
import pkg_resources
import pytest
import random
import time
Expand Down Expand Up @@ -142,6 +141,9 @@
)
from test._helpers import get_db_url, get_project

from google.cloud.sqlalchemy_spanner import __version__ as sqlalchemy_spanner_version


config.test_schema = ""


Expand Down Expand Up @@ -556,7 +558,6 @@ def test_get_foreign_keys(self, connection, use_schema):
def test_get_table_names(
self, connection, order_by, include_plain, include_views, use_schema
):

if use_schema:
schema = config.test_schema
else:
Expand Down Expand Up @@ -1913,12 +1914,10 @@ def setUp(self):
self._metadata = MetaData(bind=self._engine)

def test_user_agent(self):
dist = pkg_resources.get_distribution("sqlalchemy-spanner")

with self._engine.connect() as connection:
assert (
connection.connection.instance._client._client_info.user_agent
== "gl-" + dist.project_name + "/" + dist.version
== f"gl-sqlalchemy-spanner/{sqlalchemy_spanner_version}"
)


Expand Down
11 changes: 4 additions & 7 deletions test/test_suite_20.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import decimal
import operator
import os
import pkg_resources
import pytest
import random
import time
Expand Down Expand Up @@ -151,6 +150,9 @@
) # noqa: F401, F403
from test._helpers import get_db_url, get_project

from google.cloud.sqlalchemy_spanner import __version__ as sqlalchemy_spanner_version


config.test_schema = ""


Expand Down Expand Up @@ -872,7 +874,6 @@ def test_get_multi_foreign_keys(
scope=ObjectScope.DEFAULT,
kind=ObjectKind.TABLE,
):

"""
SPANNER OVERRIDE:
Expand Down Expand Up @@ -1088,7 +1089,6 @@ def test_get_foreign_keys(self, connection, use_schema):
(True, testing.requires.schemas), False, argnames="use_schema"
)
def test_get_table_names(self, connection, order_by, use_schema):

schema = None

_ignore_tables = [
Expand Down Expand Up @@ -1977,7 +1977,6 @@ def _round_trip(self, datatype, data):
assert isinstance(row[0], (long, int)) # noqa

def _huge_ints():

return testing.combinations(
2147483649, # 32 bits
2147483648, # 32 bits
Expand Down Expand Up @@ -2653,12 +2652,10 @@ def setUp(self):
self._metadata = MetaData()

def test_user_agent(self):
dist = pkg_resources.get_distribution("sqlalchemy-spanner")

with self._engine.connect() as connection:
assert (
connection.connection.instance._client._client_info.user_agent
== "gl-" + dist.project_name + "/" + dist.version
== f"gl-sqlalchemy-spanner/{sqlalchemy_spanner_version}"
)


Expand Down
37 changes: 37 additions & 0 deletions test/unit/test_packaging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# 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.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import subprocess
import sys


def test_namespace_package_compat(tmp_path):
# The ``google`` namespace package should not be masked
# by the presence of ``sqlalchemy-spanner``.
google = tmp_path / "google"
google.mkdir()
google.joinpath("othermod.py").write_text("")
env = dict(os.environ, PYTHONPATH=str(tmp_path))
cmd = [sys.executable, "-m", "google.othermod"]
subprocess.check_call(cmd, env=env)

# The ``google.cloud`` namespace package should not be masked
# by the presence of ``sqlalchemy-spanner``.
google_cloud = tmp_path / "google" / "cloud"
google_cloud.mkdir()
google_cloud.joinpath("othermod.py").write_text("")
env = dict(os.environ, PYTHONPATH=str(tmp_path))
cmd = [sys.executable, "-m", "google.cloud.othermod"]
subprocess.check_call(cmd, env=env)

0 comments on commit fdcceeb

Please sign in to comment.