From e24a47c64327b6975365fe3caca261c53cb69ee0 Mon Sep 17 00:00:00 2001 From: zhanghaitao3 <1085912315@qq.com> Date: Sat, 29 Nov 2025 00:14:37 +0800 Subject: [PATCH 1/3] a --- async_gaussdb/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/async_gaussdb/_version.py b/async_gaussdb/_version.py index 0e4b9efc..2c159235 100644 --- a/async_gaussdb/_version.py +++ b/async_gaussdb/_version.py @@ -14,4 +14,4 @@ import typing -__version__: typing.Final = '0.30.2' +__version__: typing.Final = '0.30.3' From 7a007ba16fbdc7764e95977a2db57e893c29a90e Mon Sep 17 00:00:00 2001 From: zhanghaitao3 <1085912315@qq.com> Date: Tue, 2 Dec 2025 01:58:28 +0800 Subject: [PATCH 2/3] Code refactoring, all content except Cpython --- .github/ISSUE_TEMPLATE.md | 6 +- .github/workflows/install-postgres.sh | 2 +- .github/workflows/tests.yml | 14 +- async_gaussdb/_testbase/__init__.py | 46 ++--- async_gaussdb/cluster.py | 132 +++++++------- async_gaussdb/connect_utils.py | 78 ++++----- async_gaussdb/connection.py | 47 ++--- async_gaussdb/protocol/codecs/array.pyx | 12 +- async_gaussdb/protocol/scram.pyx | 4 +- docs/api/index.rst | 15 +- docs/faq.rst | 20 +-- docs/installation.rst | 8 +- docs/usage.rst | 19 +- tests/test__environment.py | 14 +- tests/test_adversity.py | 2 +- tests/test_codecs.py | 6 +- tests/test_connect.py | 222 ++++++++++++------------ tests/test_listeners.py | 8 +- tests/test_pool.py | 30 ++-- tests/test_prepare.py | 2 +- tests/test_timeout.py | 4 +- tools/generate_type_map.py | 12 +- 22 files changed, 343 insertions(+), 360 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index fcce7a51..13cd29c5 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -11,9 +11,9 @@ Thank you! --> * **async_gaussdb version**: -* **PostgreSQL version**: -* **Do you use a PostgreSQL SaaS? If so, which? Can you reproduce - the issue with a local PostgreSQL install?**: +* **GaussDB version**: +* **Do you use a GaussDB SaaS? If so, which? Can you reproduce + the issue with a local GaussDB install?**: * **Python version**: * **Platform**: * **Do you use pgbouncer?**: diff --git a/.github/workflows/install-postgres.sh b/.github/workflows/install-postgres.sh index 733c7033..9b7cb0c9 100755 --- a/.github/workflows/install-postgres.sh +++ b/.github/workflows/install-postgres.sh @@ -4,7 +4,7 @@ set -Eexuo pipefail shopt -s nullglob if [[ $OSTYPE == linux* ]]; then - PGVERSION=${PGVERSION:-12} + GAUSSDBVERSION=${PGVERSION:-12} if [ -e /etc/os-release ]; then source /etc/os-release diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2d4722c4..cb7a0575 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -12,8 +12,8 @@ on: jobs: test-platforms: # NOTE: this matrix is for testing various combinations of Python and OS - # versions on the system-installed PostgreSQL version (which is usually - # fairly recent). For a PostgreSQL version matrix see the test-postgres + # versions on the system-installed GaussDB version (which is usually + # fairly recent). For a GaussDB version matrix see the test-gaussdb # job. strategy: matrix: @@ -100,11 +100,11 @@ jobs: if: "!steps.release.outputs.is_release" env: LOOP_IMPL: ${{ matrix.loop }} - PGHOST: "127.0.0.1" - PGPORT: 5432 - PGUSER: "testuser" - PGPASSWORD: "Test@123" - PGDATABASE: "test" + GAUSSDBHOST: "127.0.0.1" + GAUSSDBPORT: 5432 + GAUSSDBUSER: "testuser" + GAUSSDBPASSWORD: "Test@123" + GAUSSDBDATABASE: "test" run: | if [ "${LOOP_IMPL}" = "uvloop" ]; then env USE_UVLOOP=1 python -m unittest -v tests.suite diff --git a/async_gaussdb/_testbase/__init__.py b/async_gaussdb/_testbase/__init__.py index 9b44eee4..16987c34 100644 --- a/async_gaussdb/_testbase/__init__.py +++ b/async_gaussdb/_testbase/__init__.py @@ -20,9 +20,9 @@ import async_gaussdb -from async_gaussdb import cluster as pg_cluster -from async_gaussdb import connection as pg_connection -from async_gaussdb import pool as pg_pool +from async_gaussdb import cluster as gaussdb_cluster +from async_gaussdb import connection as gaussdb_connection +from async_gaussdb import pool as gaussdb_pool from . import fuzzer @@ -234,7 +234,7 @@ def _get_initdb_options(initdb_options=None): # Make the default superuser name stable. if 'username' not in initdb_options: - initdb_options['username'] = 'postgres' + initdb_options['username'] = 'root' return initdb_options @@ -243,13 +243,13 @@ def _init_default_cluster(initdb_options=None): global _default_cluster if _default_cluster is None: - pg_host = os.environ.get('PGHOST') - if pg_host: + gaussdb_host = os.environ.get('GAUSSDBHOST') + if gaussdb_host: # Using existing cluster, assuming it is initialized and running - _default_cluster = pg_cluster.RunningCluster() + _default_cluster = gaussdb_cluster.RunningCluster() else: _default_cluster = _init_cluster( - pg_cluster.TempCluster, + gaussdb_cluster.TempCluster, cluster_kwargs={ "data_dir_suffix": ".apgtest", }, @@ -275,8 +275,8 @@ def create_pool(dsn=None, *, setup=None, init=None, loop=None, - pool_class=pg_pool.Pool, - connection_class=pg_connection.Connection, + pool_class=gaussdb_pool.Pool, + connection_class=gaussdb_connection.Connection, record_class=async_gaussdb.Record, **connect_kwargs): return pool_class( @@ -302,7 +302,7 @@ def get_server_settings(cls): 'log_connections': 'on' } - if cls.cluster.get_pg_version() >= (11, 0): + if cls.cluster.get_gaussdb_version() >= (11, 0): # JITting messes up timing tests, and # is not essential for testing. settings['jit'] = 'off' @@ -349,17 +349,17 @@ def get_connection_spec(cls, kwargs={}): if kwargs.get('dsn'): conn_spec.pop('host') conn_spec.update(kwargs) - if not os.environ.get('PGHOST') and not kwargs.get('dsn'): + if not os.environ.get('GAUSSDBHOST') and not kwargs.get('dsn'): if 'database' not in conn_spec: conn_spec['database'] = 'postgres' if 'user' not in conn_spec: - conn_spec['user'] = 'postgres' + conn_spec['user'] = 'root' return conn_spec @classmethod def connect(cls, **kwargs): conn_spec = cls.get_connection_spec(kwargs) - return pg_connection.connect(**conn_spec, loop=cls.loop) + return gaussdb_connection.connect(**conn_spec, loop=cls.loop) def setUp(self): super().setUp() @@ -371,8 +371,8 @@ def tearDown(self): pool.terminate() self._pools = [] - def create_pool(self, pool_class=pg_pool.Pool, - connection_class=pg_connection.Connection, **kwargs): + def create_pool(self, pool_class=gaussdb_pool.Pool, + connection_class=gaussdb_connection.Connection, **kwargs): conn_spec = self.get_connection_spec(kwargs) pool = create_pool(loop=self.loop, pool_class=pool_class, connection_class=connection_class, **conn_spec) @@ -457,7 +457,7 @@ class HotStandbyTestCase(ClusterTestCase): @classmethod def setup_cluster(cls): - cls.master_cluster = cls.new_cluster(pg_cluster.TempCluster) + cls.master_cluster = cls.new_cluster(gaussdb_cluster.TempCluster) cls.start_cluster( cls.master_cluster, server_settings={ @@ -471,7 +471,7 @@ def setup_cluster(cls): try: con = cls.loop.run_until_complete( cls.master_cluster.connect( - database='postgres', user='postgres', loop=cls.loop)) + database='postgres', user='root', loop=cls.loop)) cls.loop.run_until_complete( con.execute(''' @@ -483,7 +483,7 @@ def setup_cluster(cls): conn_spec = cls.master_cluster.get_connection_spec() cls.standby_cluster = cls.new_cluster( - pg_cluster.HotStandbyCluster, + gaussdb_cluster.HotStandbyCluster, cluster_kwargs={ 'master': conn_spec, 'replication_user': 'replication' @@ -506,11 +506,11 @@ def get_cluster_connection_spec(cls, cluster, kwargs={}): if kwargs.get('dsn'): conn_spec.pop('host') conn_spec.update(kwargs) - if not os.environ.get('PGHOST') and not kwargs.get('dsn'): + if not os.environ.get('GAUSSDBHOST') and not kwargs.get('dsn'): if 'database' not in conn_spec: conn_spec['database'] = 'postgres' if 'user' not in conn_spec: - conn_spec['user'] = 'postgres' + conn_spec['user'] = 'root' return conn_spec @classmethod @@ -532,7 +532,7 @@ def get_connection_spec(cls, kwargs={}): @classmethod def connect_primary(cls, **kwargs): conn_spec = cls.get_cluster_connection_spec(cls.master_cluster, kwargs) - return pg_connection.connect(**conn_spec, loop=cls.loop) + return gaussdb_connection.connect(**conn_spec, loop=cls.loop) @classmethod def connect_standby(cls, **kwargs): @@ -540,4 +540,4 @@ def connect_standby(cls, **kwargs): cls.standby_cluster, kwargs ) - return pg_connection.connect(**conn_spec, loop=cls.loop) + return gaussdb_connection.connect(**conn_spec, loop=cls.loop) diff --git a/async_gaussdb/cluster.py b/async_gaussdb/cluster.py index 4d0e0332..d19c08b1 100644 --- a/async_gaussdb/cluster.py +++ b/async_gaussdb/cluster.py @@ -75,21 +75,21 @@ class ClusterError(Exception): class Cluster: - def __init__(self, data_dir, *, pg_config_path=None): + def __init__(self, data_dir, *, pg_config=None): self._data_dir = data_dir - self._pg_config_path = pg_config_path - self._pg_bin_dir = ( - os.environ.get('PGINSTALLATION') - or os.environ.get('PGBIN') + self._pg_config = pg_config + self._gaussdb_bin_dir = ( + os.environ.get('GAUSSDBINSTALLATION') + or os.environ.get('GAUSSDBBIN') ) - self._pg_ctl = None + self._gs_ctl = None self._daemon_pid = None self._daemon_process = None self._connection_addr = None self._connection_spec_override = None - def get_pg_version(self): - return self._pg_version + def get_gaussdb_version(self): + return self._gaussdb_version def is_managed(self): return True @@ -98,11 +98,11 @@ def get_data_dir(self): return self._data_dir def get_status(self): - if self._pg_ctl is None: + if self._gs_ctl is None: self._init_env() process = subprocess.run( - [self._pg_ctl, 'status', '-D', self._data_dir], + [self._gs_ctl, 'status', '-D', self._data_dir], stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = process.stdout, process.stderr @@ -115,13 +115,13 @@ def get_status(self): r = re.match(r'.*PID\s?:\s+(\d+).*', stdout.decode()) if not r: raise ClusterError( - 'could not parse pg_ctl status output: {}'.format( + 'could not parse gs_ctl status output: {}'.format( stdout.decode())) self._daemon_pid = int(r.group(1)) return self._test_connection(timeout=0) else: raise ClusterError( - 'pg_ctl status exited with status {:d}: {}'.format( + 'gs_ctl status exited with status {:d}: {}'.format( process.returncode, stderr)) async def connect(self, loop=None, **kwargs): @@ -149,7 +149,7 @@ def init(self, **settings): os.makedirs(self._data_dir, exist_ok=True) process = subprocess.run( - [self._pg_ctl, 'init', '-D', self._data_dir] + extra_args, + [self._gs_ctl, 'init', '-D', self._data_dir] + extra_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=self._data_dir, @@ -159,7 +159,7 @@ def init(self, **settings): if process.returncode != 0: raise ClusterError( - 'pg_ctl init exited with status {:d}:\n{}'.format( + 'gs_ctl init exited with status {:d}:\n{}'.format( process.returncode, output.decode())) return output.decode() @@ -197,7 +197,7 @@ def start(self, wait=60, *, server_settings={}, **opts): server_settings['ssl_key_file'] = keyfile if sockdir is not None: - if self._pg_version < (9, 3): + if self._gaussdb_version < (9, 3): sockdir_opt = 'unix_socket_directory' else: sockdir_opt = 'unix_socket_directories' @@ -208,7 +208,7 @@ def start(self, wait=60, *, server_settings={}, **opts): extra_args.extend(['-c', '{}={}'.format(k, v)]) if _system == 'Windows': - # On Windows we have to use pg_ctl as direct execution + # On Windows we have to use gs_ctl as direct execution # of GaussDB daemon under an Administrative account # is not permitted and there is no easy way to drop # privileges. @@ -217,7 +217,7 @@ def start(self, wait=60, *, server_settings={}, **opts): print( 'async_gaussdb.cluster: Running', ' '.join([ - self._pg_ctl, 'start', '-D', self._data_dir, + self._gs_ctl, 'start', '-D', self._data_dir, '-o', ' '.join(extra_args) ]), file=sys.stderr, @@ -226,7 +226,7 @@ def start(self, wait=60, *, server_settings={}, **opts): stdout = subprocess.DEVNULL process = subprocess.run( - [self._pg_ctl, 'start', '-D', self._data_dir, + [self._gs_ctl, 'start', '-D', self._data_dir, '-o', ' '.join(extra_args)], stdout=stdout, stderr=subprocess.STDOUT, @@ -239,7 +239,7 @@ def start(self, wait=60, *, server_settings={}, **opts): else: stderr = '' raise ClusterError( - 'pg_ctl start exited with status {:d}{}'.format( + 'gs_ctl start exited with status {:d}{}'.format( process.returncode, stderr)) else: if os.getenv('async_gaussdb_DEBUG_SERVER'): @@ -249,7 +249,7 @@ def start(self, wait=60, *, server_settings={}, **opts): self._daemon_process = \ subprocess.Popen( - [self._postgres, '-D', self._data_dir, *extra_args], + [self._gaussdb, '-D', self._data_dir, *extra_args], stdout=stdout, stderr=subprocess.STDOUT, cwd=self._data_dir, @@ -266,7 +266,7 @@ def reload(self): raise ClusterError('cannot reload: cluster is not running') process = subprocess.run( - [self._pg_ctl, 'reload', '-D', self._data_dir], + [self._gs_ctl, 'reload', '-D', self._data_dir], stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=self._data_dir, @@ -276,12 +276,12 @@ def reload(self): if process.returncode != 0: raise ClusterError( - 'pg_ctl stop exited with status {:d}: {}'.format( + 'gs_ctl stop exited with status {:d}: {}'.format( process.returncode, stderr.decode())) def stop(self, wait=60): process = subprocess.run( - [self._pg_ctl, 'stop', '-D', self._data_dir, '-t', str(wait), + [self._gs_ctl, 'stop', '-D', self._data_dir, '-t', str(wait), '-m', 'fast'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, @@ -292,7 +292,7 @@ def stop(self, wait=60): if process.returncode != 0: raise ClusterError( - 'pg_ctl stop exited with status {:d}: {}'.format( + 'gs_ctl stop exited with status {:d}: {}'.format( process.returncode, stderr.decode())) if (self._daemon_process is not None and @@ -349,9 +349,9 @@ def reset_wal(self, *, oid=None, xid=None): opts.append(self._data_dir) try: - reset_wal = self._find_pg_binary('pg_resetwal') + reset_wal = self._find_gaussdb_binary('pg_resetwal') except ClusterError: - reset_wal = self._find_pg_binary('pg_resetxlog') + reset_wal = self._find_gaussdb_binary('pg_resetxlog') process = subprocess.run( [reset_wal] + opts, @@ -446,18 +446,18 @@ def trust_local_replication_by(self, user): self.reload() def _init_env(self): - if not self._pg_bin_dir: - pg_config = self._find_pg_config(self._pg_config_path) - pg_config_data = self._run_pg_config(pg_config) + if not self._gaussdb_bin_dir: + pg_config = self._find_gaussdb_config(self._pg_config) + pg_config_data = self._run_gaussdb_config(pg_config) - self._pg_bin_dir = pg_config_data.get('bindir') - if not self._pg_bin_dir: + self._gaussdb_bin_dir = pg_config_data.get('bindir') + if not self._gaussdb_bin_dir: raise ClusterError( 'pg_config output did not provide the BINDIR value') - self._pg_ctl = self._find_pg_binary('pg_ctl') - self._postgres = self._find_pg_binary('postgres') - self._pg_version = self._get_pg_version() + self._gs_ctl = self._find_gaussdb_binary('gs_ctl') + self._gaussdb = self._find_gaussdb_binary('gaussdb') + self._gaussdb_version = self._get_gaussdb_version() def _connection_addr_from_pidfile(self): pidfile = os.path.join(self._data_dir, 'postmaster.pid') @@ -471,12 +471,12 @@ def _connection_addr_from_pidfile(self): lines = piddata.splitlines() if len(lines) < 6: - # A complete postgres pidfile is at least 6 lines + # A complete gaussdb pidfile is at least 6 lines return None pmpid = int(lines[0]) if self._daemon_pid and pmpid != self._daemon_pid: - # This might be an old pidfile left from previous postgres + # This might be an old pidfile left from previous gaussdb # daemon run. return None @@ -521,7 +521,7 @@ def _test_connection(self, timeout=60): try: con = loop.run_until_complete( async_gaussdb.connect(database='postgres', - user='postgres', + user='root', timeout=5, loop=loop, **self._connection_addr)) @@ -543,9 +543,9 @@ def _test_connection(self, timeout=60): return 'running' - def _run_pg_config(self, pg_config_path): + def _run_gaussdb_config(self, pg_config): process = subprocess.run( - pg_config_path, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + pg_config, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = process.stdout, process.stderr if process.returncode != 0: @@ -561,36 +561,36 @@ def _run_pg_config(self, pg_config_path): return config - def _find_pg_config(self, pg_config_path): - if pg_config_path is None: + def _find_gaussdb_config(self, pg_config): + if pg_config is None: pg_install = ( - os.environ.get('PGINSTALLATION') - or os.environ.get('PGBIN') + os.environ.get('GAUSSDBINSTALLATION') + or os.environ.get('GAUSSDBBIN') ) if pg_install: - pg_config_path = platform_exe( + pg_config = platform_exe( os.path.join(pg_install, 'pg_config')) else: pathenv = os.environ.get('PATH').split(os.pathsep) for path in pathenv: - pg_config_path = platform_exe( + pg_config = platform_exe( os.path.join(path, 'pg_config')) - if os.path.exists(pg_config_path): + if os.path.exists(pg_config): break else: - pg_config_path = None + pg_config = None - if not pg_config_path: + if not pg_config: raise ClusterError('could not find pg_config executable') - if not os.path.isfile(pg_config_path): + if not os.path.isfile(pg_config): raise ClusterError('{!r} is not an executable'.format( - pg_config_path)) + pg_config)) - return pg_config_path + return pg_config - def _find_pg_binary(self, binary): - bpath = platform_exe(os.path.join(self._pg_bin_dir, binary)) + def _find_gaussdb_binary(self, binary): + bpath = platform_exe(os.path.join(self._gaussdb_bin_dir, binary)) if not os.path.isfile(bpath): raise ClusterError( @@ -599,19 +599,19 @@ def _find_pg_binary(self, binary): return bpath - def _get_pg_version(self): + def _get_gaussdb_version(self): process = subprocess.run( - [self._postgres, '--version'], + [self._gaussdb, '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = process.stdout, process.stderr if process.returncode != 0: raise ClusterError( - 'postgres --version exited with status {:d}: {}'.format( + 'gaussdb --version exited with status {:d}: {}'.format( process.returncode, stderr)) version_string = stdout.decode('utf-8').strip(' \n') - prefix = 'postgres (PostgreSQL) ' + prefix = 'gaussdb' if not version_string.startswith(prefix): raise ClusterError( 'could not determine server version from {!r}'.format( @@ -624,29 +624,29 @@ def _get_pg_version(self): class TempCluster(Cluster): def __init__(self, *, data_dir_suffix=None, data_dir_prefix=None, - data_dir_parent=None, pg_config_path=None): + data_dir_parent=None, pg_config=None): self._data_dir = _mkdtemp(suffix=data_dir_suffix, prefix=data_dir_prefix, dir=data_dir_parent) - super().__init__(self._data_dir, pg_config_path=pg_config_path) + super().__init__(self._data_dir, pg_config=pg_config) class HotStandbyCluster(TempCluster): def __init__(self, *, master, replication_user, data_dir_suffix=None, data_dir_prefix=None, - data_dir_parent=None, pg_config_path=None): + data_dir_parent=None, pg_config=None): self._master = master self._repl_user = replication_user super().__init__( data_dir_suffix=data_dir_suffix, data_dir_prefix=data_dir_prefix, data_dir_parent=data_dir_parent, - pg_config_path=pg_config_path) + pg_config=pg_config) def _init_env(self): super()._init_env() - self._pg_basebackup = self._find_pg_binary('pg_basebackup') + self._gs_basebackup = self._find_gaussdb_binary('gs_basebackup') def init(self, **settings): """Initialize cluster.""" @@ -656,7 +656,7 @@ def init(self, **settings): self._data_dir)) process = subprocess.run( - [self._pg_basebackup, '-h', self._master['host'], + [self._gs_basebackup, '-h', self._master['host'], '-p', self._master['port'], '-D', self._data_dir, '-U', self._repl_user], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) @@ -665,10 +665,10 @@ def init(self, **settings): if process.returncode != 0: raise ClusterError( - 'pg_basebackup init exited with status {:d}:\n{}'.format( + 'gs_basebackup init exited with status {:d}:\n{}'.format( process.returncode, output.decode())) - if self._pg_version < (12, 0): + if self._gaussdb_version < (12, 0): with open(os.path.join(self._data_dir, 'recovery.conf'), 'w') as f: f.write(textwrap.dedent("""\ standby_mode = 'on' @@ -684,7 +684,7 @@ def init(self, **settings): return output.decode() def start(self, wait=60, *, server_settings={}, **opts): - if self._pg_version >= (12, 0): + if self._gaussdb_version >= (12, 0): server_settings = server_settings.copy() server_settings['primary_conninfo'] = ( '"host={host} port={port} user={user}"'.format( diff --git a/async_gaussdb/connect_utils.py b/async_gaussdb/connect_utils.py index 902476da..a1e6d38d 100644 --- a/async_gaussdb/connect_utils.py +++ b/async_gaussdb/connect_utils.py @@ -82,9 +82,9 @@ class SSLNegotiation(compat.StrEnum): if _system == 'Windows': - PGPASSFILE = 'pgpass.conf' + GAUSSDBPASSFILE = 'gaussdbpass.conf' else: - PGPASSFILE = '.pgpass' + GAUSSDBPASSFILE = '.gaussdbpass' def _read_password_file(passfile: pathlib.Path) \ @@ -130,13 +130,13 @@ def _read_password_file(passfile: pathlib.Path) \ return passtab -def _read_password_from_pgpass( +def _read_password_from_gaussdbpass( *, passfile: typing.Optional[pathlib.Path], hosts: typing.List[str], ports: typing.List[int], database: str, user: str): - """Parse the pgpass file and return the matching password. + """Parse the gaussdbpass file and return the matching password. :return: Password string, if found, ``None`` otherwise. @@ -194,7 +194,7 @@ def _parse_hostlist(hostlist, port, *, unquote=False): hostlist_ports = [] if not port: - portspec = os.environ.get('PGPORT') + portspec = os.environ.get('GAUSSDBPORT') if portspec: if ',' in portspec: default_port = [int(p) for p in portspec.split(',')] @@ -274,7 +274,7 @@ def _parse_connect_dsn_and_args(*, dsn, host, port, user, direct_tls, server_settings, target_session_attrs, krbsrvname, gsslib): # `auth_hosts` is the version of host information for the purposes - # of reading the pgpass file. + # of reading the gaussdbpass file. auth_hosts = None sslcert = sslkey = sslrootcert = sslcrl = sslpassword = None ssl_min_protocol_version = ssl_max_protocol_version = None @@ -283,10 +283,10 @@ def _parse_connect_dsn_and_args(*, dsn, host, port, user, if dsn: parsed = urllib.parse.urlparse(dsn) - if parsed.scheme not in {'postgresql', 'postgres', 'gaussdb'}: + if parsed.scheme not in {'gaussdb'}: raise exceptions.ClientConfigurationError( 'invalid DSN: scheme is expected to be either ' - '"gaussdb" or "postgresql" or "postgres", got {!r}' + '"gaussdb", got {!r}' .format(parsed.scheme)) if parsed.netloc: @@ -416,7 +416,7 @@ def _parse_connect_dsn_and_args(*, dsn, host, port, user, server_settings = {**query, **server_settings} if not host: - hostspec = os.environ.get('PGHOST') + hostspec = os.environ.get('GAUSSDBHOST') if hostspec: host, port = _parse_hostlist(hostspec, port) @@ -426,7 +426,7 @@ def _parse_connect_dsn_and_args(*, dsn, host, port, user, if _system == 'Windows': host = ['localhost'] else: - host = ['/run/postgresql', '/var/run/postgresql', + host = ['/run/gaussdb', '/var/run/gaussdb', '/tmp', '/private/tmp', 'localhost'] if not isinstance(host, (list, tuple)): @@ -436,7 +436,7 @@ def _parse_connect_dsn_and_args(*, dsn, host, port, user, auth_hosts = host if not port: - portspec = os.environ.get('PGPORT') + portspec = os.environ.get('GAUSSDBPORT') if portspec: if ',' in portspec: port = [int(p) for p in portspec.split(',')] @@ -454,15 +454,15 @@ def _parse_connect_dsn_and_args(*, dsn, host, port, user, port = _validate_port_spec(host, port) if user is None: - user = os.getenv('PGUSER') + user = os.getenv('GAUSSDBUSER') if not user: user = getpass.getuser() if password is None: - password = os.getenv('PGPASSWORD') + password = os.getenv('GAUSSDBPASSWORD') if database is None: - database = os.getenv('PGDATABASE') + database = os.getenv('GAUSSDBDATABASE') if database is None: database = user @@ -477,19 +477,19 @@ def _parse_connect_dsn_and_args(*, dsn, host, port, user, if password is None: if passfile is None: - passfile = os.getenv('PGPASSFILE') + passfile = os.getenv('GAUSSDBPASSFILE') if passfile is None: homedir = compat.get_gaussdb_home_directory() if homedir: - passfile = homedir / PGPASSFILE + passfile = homedir / GAUSSDBPASSFILE else: passfile = None else: passfile = pathlib.Path(passfile) if passfile is not None: - password = _read_password_from_pgpass( + password = _read_password_from_gaussdbpass( hosts=auth_hosts, ports=port, database=database, user=user, passfile=passfile) @@ -512,7 +512,7 @@ def _parse_connect_dsn_and_args(*, dsn, host, port, user, 'could not determine the database address to connect to') if ssl is None: - ssl = os.getenv('PGSSLMODE') + ssl = os.getenv('GAUSSDBSSLMODE') if ssl is None and have_tcp_addrs: ssl = 'prefer' @@ -523,7 +523,7 @@ def _parse_connect_dsn_and_args(*, dsn, host, port, user, ) else: if sslnegotiation is None: - sslnegotiation = os.environ.get("PGSSLNEGOTIATION") + sslnegotiation = os.environ.get("GAUSSDBSSLNEGOTIATION") if sslnegotiation is not None: try: @@ -557,7 +557,7 @@ def _parse_connect_dsn_and_args(*, dsn, host, port, user, ssl.verify_mode = ssl_module.CERT_NONE else: if sslrootcert is None: - sslrootcert = os.getenv('PGSSLROOTCERT') + sslrootcert = os.getenv('GAUSSDBSSLROOTCERT') if sslrootcert: ssl.load_verify_locations(cafile=sslrootcert) ssl.verify_mode = ssl_module.CERT_REQUIRED @@ -578,7 +578,7 @@ def _parse_connect_dsn_and_args(*, dsn, host, port, user, ): if sslmode > SSLMode.require: if sslrootcert is None: - sslrootcert = '~/.postgresql/root.crt' + sslrootcert = '~/.gaussdb/root.crt' detail = ( 'Could not determine location of user ' 'home directory (HOME is either unset, ' @@ -603,7 +603,7 @@ def _parse_connect_dsn_and_args(*, dsn, host, port, user, ssl.verify_mode = ssl_module.CERT_REQUIRED if sslcrl is None: - sslcrl = os.getenv('PGSSLCRL') + sslcrl = os.getenv('GAUSSDBSSLCRL') if sslcrl: ssl.load_verify_locations(cafile=sslcrl) ssl.verify_flags |= ssl_module.VERIFY_CRL_CHECK_CHAIN @@ -622,21 +622,21 @@ def _parse_connect_dsn_and_args(*, dsn, host, port, user, ssl_module.VERIFY_CRL_CHECK_CHAIN if sslkey is None: - sslkey = os.getenv('PGSSLKEY') + sslkey = os.getenv('GAUSSDBSSLKEY') if not sslkey: - sslkey = _dot_gaussdb_path('postgresql.key') + sslkey = _dot_gaussdb_path('gaussdb.key') if sslkey is not None and not sslkey.exists(): sslkey = None if not sslpassword: sslpassword = '' if sslcert is None: - sslcert = os.getenv('PGSSLCERT') + sslcert = os.getenv('GAUSSDBSSLCERT') if sslcert: ssl.load_cert_chain( sslcert, keyfile=sslkey, password=lambda: sslpassword ) else: - sslcert = _dot_gaussdb_path('postgresql.crt') + sslcert = _dot_gaussdb_path('gaussdb.crt') if sslcert is not None: try: ssl.load_cert_chain( @@ -654,7 +654,7 @@ def _parse_connect_dsn_and_args(*, dsn, host, port, user, ssl.keylog_filename = keylogfile if ssl_min_protocol_version is None: - ssl_min_protocol_version = os.getenv('PGSSLMINPROTOCOLVERSION') + ssl_min_protocol_version = os.getenv('GAUSSDBSSLMINPROTOCOLVERSION') if ssl_min_protocol_version: ssl.minimum_version = _parse_tls_version( ssl_min_protocol_version @@ -663,7 +663,7 @@ def _parse_connect_dsn_and_args(*, dsn, host, port, user, ssl.minimum_version = _parse_tls_version('TLSv1.2') if ssl_max_protocol_version is None: - ssl_max_protocol_version = os.getenv('PGSSLMAXPROTOCOLVERSION') + ssl_max_protocol_version = os.getenv('GAUSSDBSSLMAXPROTOCOLVERSION') if ssl_max_protocol_version: ssl.maximum_version = _parse_tls_version( ssl_max_protocol_version @@ -685,7 +685,7 @@ def _parse_connect_dsn_and_args(*, dsn, host, port, user, if target_session_attrs is None: target_session_attrs = os.getenv( - "PGTARGETSESSIONATTRS", SessionAttribute.any + "GAUSSDBTARGETSESSIONATTRS", SessionAttribute.any ) try: target_session_attrs = SessionAttribute(target_session_attrs) @@ -699,10 +699,10 @@ def _parse_connect_dsn_and_args(*, dsn, host, port, user, ) from None if krbsrvname is None: - krbsrvname = os.getenv('PGKRBSRVNAME') + krbsrvname = os.getenv('GAUSSDBKRBSRVNAME') if gsslib is None: - gsslib = os.getenv('PGGSSLIB') + gsslib = os.getenv('GAUSSDBGSSLIB') if gsslib is None: gsslib = 'sspi' if _system == 'Windows' else 'gssapi' if gsslib not in {'gssapi', 'sspi'}: @@ -850,12 +850,12 @@ async def _create_ssl_connection( else: new_tr = tr - pg_proto = protocol_factory() - pg_proto.is_ssl = do_ssl_upgrade - pg_proto.connection_made(new_tr) - new_tr.set_protocol(pg_proto) + gaussdb_proto = protocol_factory() + gaussdb_proto.is_ssl = do_ssl_upgrade + gaussdb_proto.connection_made(new_tr) + new_tr.set_protocol(gaussdb_proto) - return new_tr, pg_proto + return new_tr, gaussdb_proto else: conn_factory = functools.partial( loop.create_connection, protocol_factory) @@ -870,9 +870,9 @@ async def _create_ssl_connection( tr.close() try: - new_tr, pg_proto = await conn_factory(sock=sock) - pg_proto.is_ssl = do_ssl_upgrade - return new_tr, pg_proto + new_tr, gaussdb_proto = await conn_factory(sock=sock) + gaussdb_proto.is_ssl = do_ssl_upgrade + return new_tr, gaussdb_proto except (Exception, asyncio.CancelledError): sock.close() raise diff --git a/async_gaussdb/connection.py b/async_gaussdb/connection.py index b6b3639d..829c6567 100644 --- a/async_gaussdb/connection.py +++ b/async_gaussdb/connection.py @@ -483,7 +483,7 @@ async def _get_statement( # Mark this anonymous prepared statement as "unprepared", # causing it to get re-Parsed in next bind_execute. # We always do this when stmt_cache_size is set to 0 assuming - # people are running PgBouncer which is mishandling implicit + # people are running Bouncer which is mishandling implicit # transactions. statement.mark_unprepared() @@ -837,7 +837,7 @@ async def copy_from_table(self, table_name, *, output, >>> import async_gaussdb >>> import asyncio >>> async def run(): - ... con = await async_gaussdb.connect(user='postgres') + ... con = await async_gaussdb.connect(user='root') ... result = await con.copy_from_table( ... 'mytable', columns=('foo', 'bar'), ... output='file.csv', format='csv') @@ -904,7 +904,7 @@ async def copy_from_query(self, query, *args, output, >>> import async_gaussdb >>> import asyncio >>> async def run(): - ... con = await async_gaussdb.connect(user='postgres') + ... con = await async_gaussdb.connect(user='root') ... result = await con.copy_from_query( ... 'SELECT foo, bar FROM mytable WHERE foo > $1', 10, ... output='file.csv', format='csv') @@ -980,7 +980,7 @@ async def copy_to_table(self, table_name, *, source, >>> import async_gaussdb >>> import asyncio >>> async def run(): - ... con = await async_gaussdb.connect(user='postgres') + ... con = await async_gaussdb.connect(user='root') ... result = await con.copy_to_table( ... 'mytable', source='datafile.tbl') ... print(result) @@ -1058,7 +1058,7 @@ async def copy_records_to_table(self, table_name, *, records, >>> import async_gaussdb >>> import asyncio >>> async def run(): - ... con = await async_gaussdb.connect(user='postgres') + ... con = await async_gaussdb.connect(user='root') ... result = await con.copy_records_to_table( ... 'mytable', records=[ ... (1, 'foo', 'bar'), @@ -1075,7 +1075,7 @@ async def copy_records_to_table(self, table_name, *, records, >>> import async_gaussdb >>> import asyncio >>> async def run(): - ... con = await async_gaussdb.connect(user='postgres') + ... con = await async_gaussdb.connect(user='root') ... async def record_gen(size): ... for i in range(size): ... yield (i,) @@ -1323,7 +1323,7 @@ async def set_type_codec(self, typename, *, >>> import datetime >>> from dateutil.relativedelta import relativedelta >>> async def run(): - ... con = await async_gaussdb.connect(user='postgres') + ... con = await async_gaussdb.connect(user='root') ... def encoder(delta): ... ndelta = delta.normalized() ... return (ndelta.years * 12 + ndelta.months, @@ -1837,7 +1837,7 @@ async def reload_schema_state(self): ... # Initial schema: ... # CREATE TYPE custom AS (x int, y int); ... # CREATE TABLE tbl(id int, info custom); - ... con = await async_gaussdb.connect(user='postgres') + ... con = await async_gaussdb.connect(user='root') ... async with con.transaction(): ... # Prevent concurrent changes in the table ... await con.execute('LOCK TABLE tbl') @@ -2135,9 +2135,9 @@ async def connect(dsn=None, *, If not specified, async_gaussdb will try the following, in order: - host address(es) parsed from the *dsn* argument, - - the value of the ``PGHOST`` environment variable, + - the value of the ``GAUSSDBHOST`` environment variable, - on Unix, common directories used for GaussDBSQL Unix-domain - sockets: ``"/run/postgresql"``, ``"/var/run/postgresl"``, + sockets: ``"/run/gaussdb"``, ``"/var/run/gaussdb"``, ``"/var/pgsql_socket"``, ``"/private/tmp"``, and ``"/tmp"``, - ``"localhost"``. @@ -2150,27 +2150,27 @@ async def connect(dsn=None, *, addresses. If not specified, the value parsed from the *dsn* argument is used, - or the value of the ``PGPORT`` environment variable, or ``5432`` if + or the value of the ``GAUSSDBPORT`` environment variable, or ``5432`` if neither is specified. :param user: The name of the database role used for authentication. If not specified, the value parsed from the *dsn* argument is used, - or the value of the ``PGUSER`` environment variable, or the + or the value of the ``GAUSSDBUSER`` environment variable, or the operating system name of the user running the application. :param database: The name of the database to connect to. If not specified, the value parsed from the *dsn* argument is used, - or the value of the ``PGDATABASE`` environment variable, or the + or the value of the ``GAUSSDBDATABASE`` environment variable, or the computed value of the *user* argument. :param password: Password to be used for authentication, if the server requires one. If not specified, the value parsed from the *dsn* argument - is used, or the value of the ``PGPASSWORD`` environment variable. + is used, or the value of the ``GAUSSDBPASSWORD`` environment variable. Note that the use of the environment variable is discouraged as other users and applications may be able to read it without needing specific privileges. It is recommended to use *passfile* instead. @@ -2181,7 +2181,7 @@ async def connect(dsn=None, *, :param passfile: The name of the file used to store passwords - (defaults to ``~/.pgpass``, or ``%APPDATA%\postgresql\pgpass.conf`` + (defaults to ``~/.gaussdbpass``, or ``%APPDATA%\gaussdb\gaussdbpass.conf`` on Windows). :param loop: @@ -2261,7 +2261,7 @@ async def connect(dsn=None, *, ... "path/to/client.cert", ... keyfile="path/to/client.key", ... ) - ... con = await async_gaussdb.connect(user='postgres', ssl=sslctx) + ... con = await async_gaussdb.connect(user='root', ssl=sslctx) ... await con.close() >>> asyncio.run(main()) @@ -2278,7 +2278,7 @@ async def connect(dsn=None, *, ... ssl.Purpose.SERVER_AUTH) ... sslctx.check_hostname = False ... sslctx.verify_mode = ssl.CERT_NONE - ... con = await async_gaussdb.connect(user='postgres', ssl=sslctx) + ... con = await async_gaussdb.connect(user='root', ssl=sslctx) ... await con.close() >>> asyncio.run(main()) @@ -2314,7 +2314,7 @@ async def connect(dsn=None, *, return any of them. If not specified, the value parsed from the *dsn* argument is used, - or the value of the ``PGTARGETSESSIONATTRS`` environment variable, + or the value of the ``GAUSSDBTARGETSESSIONATTRS`` environment variable, or ``"any"`` if neither is specified. :param str krbsrvname: @@ -2334,7 +2334,7 @@ async def connect(dsn=None, *, >>> import async_gaussdb >>> import asyncio >>> async def run(): - ... con = await async_gaussdb.connect(user='postgres') + ... con = await async_gaussdb.connect(user='root') ... types = await con.fetch('SELECT * FROM pg_type') ... print(types) ... @@ -2385,7 +2385,7 @@ async def connect(dsn=None, *, .. versionchanged:: 0.25.0 The ``sslcert``, ``sslkey``, ``sslrootcert``, and ``sslcrl`` options in the *dsn* argument now have consistent default values of files under - ``~/.postgresql/`` as libpq. + ``~/.gaussdb/`` as libpq. .. versionchanged:: 0.26.0 Added the *direct_tls* parameter. @@ -2674,7 +2674,10 @@ def _detect_server_capabilities(server_version, connection_settings): sql_close_all = False jit = False sql_copy_from_where = False - elif hasattr(connection_settings, 'sql_mode') or hasattr(connection_settings, 'session_respool'): + elif ( + hasattr(connection_settings, 'sql_mode') + or hasattr(connection_settings, 'session_respool') + ): # Standard GaussDBSQL serve advisory_locks = True notifications = False @@ -2684,7 +2687,7 @@ def _detect_server_capabilities(server_version, connection_settings): jit = False sql_copy_from_where = False else: - # Standard Postgresql server assumed. + # Standard server assumed. advisory_locks = True notifications = True plpgsql = True diff --git a/async_gaussdb/protocol/codecs/array.pyx b/async_gaussdb/protocol/codecs/array.pyx index 8d7219c1..85dfcdf9 100644 --- a/async_gaussdb/protocol/codecs/array.pyx +++ b/async_gaussdb/protocol/codecs/array.pyx @@ -419,7 +419,7 @@ cdef textarray_decode(ConnectionSettings settings, FRBuffer *buf, # Make a copy of array data since we will be mutating it for # the purposes of element decoding. - s = pgproto.text_decode(settings, buf) + s = gaussdbproto.text_decode(settings, buf) array_text = cpythonx.PyUnicode_AsUCS4Copy(s) try: @@ -648,7 +648,7 @@ cdef _textarray_decode(ConnectionSettings settings, # Prepare the element buffer and call the text decoder # for the element type. - pgproto.as_pg_string_and_size( + gaussdbproto.as_pg_string_and_size( settings, item_text, &pg_item_str, &pg_item_len) frb_init(&item_buf, pg_item_str, pg_item_len) item = decoder(settings, &item_buf, decoder_arg) @@ -822,12 +822,12 @@ cdef _infer_array_dims(const Py_UCS4 *array_text, cdef uint4_encode_ex(ConnectionSettings settings, WriteBuffer buf, object obj, const void *arg): - return pgproto.uint4_encode(settings, buf, obj) + return gaussdbproto.uint4_encode(settings, buf, obj) cdef uint4_decode_ex(ConnectionSettings settings, FRBuffer *buf, const void *arg): - return pgproto.uint4_decode(settings, buf) + return gaussdbproto.uint4_decode(settings, buf) cdef arrayoid_encode(ConnectionSettings settings, WriteBuffer buf, items): @@ -841,12 +841,12 @@ cdef arrayoid_decode(ConnectionSettings settings, FRBuffer *buf): cdef text_encode_ex(ConnectionSettings settings, WriteBuffer buf, object obj, const void *arg): - return pgproto.text_encode(settings, buf, obj) + return gaussdbproto.text_encode(settings, buf, obj) cdef text_decode_ex(ConnectionSettings settings, FRBuffer *buf, const void *arg): - return pgproto.text_decode(settings, buf) + return gaussdbproto.text_decode(settings, buf) cdef arraytext_encode(ConnectionSettings settings, WriteBuffer buf, items): diff --git a/async_gaussdb/protocol/scram.pyx b/async_gaussdb/protocol/scram.pyx index b1ac19b1..ce969d3e 100644 --- a/async_gaussdb/protocol/scram.pyx +++ b/async_gaussdb/protocol/scram.pyx @@ -34,7 +34,7 @@ cdef class SCRAMAuthentication: SASL authentication using SCRAM and presents a client with the methods it supports. At present, those are SCRAM-SHA-256, and, on servers that are built with OpenSSL and - are PG11+, SCRAM-SHA-256-PLUS (which supports channel binding, more on that + SCRAM-SHA-256-PLUS (which supports channel binding, more on that below) - The client sends a "first message" to the server, where it chooses which @@ -263,7 +263,7 @@ cdef class SCRAMAuthentication: # SASLprep processing. # If the password fails SASLprep, the password should still be sent # and - # using the `pg_saslprep` function + # using the `saslprep` function normalized_password = original_password # if the original password is an ASCII string or fails to encode as a # UTF-8 string, then no further action is needed diff --git a/docs/api/index.rst b/docs/api/index.rst index cb0a7ee5..b816d50c 100644 --- a/docs/api/index.rst +++ b/docs/api/index.rst @@ -5,7 +5,7 @@ API Reference ============= .. module:: async_gaussdb - :synopsis: A fast PostgreSQL Database Client Library for Python/asyncio + :synopsis: A fast GaussDB Database Client Library for Python/asyncio .. currentmodule:: async_gaussdb @@ -27,7 +27,7 @@ Connection Prepared Statements =================== -Prepared statements are a PostgreSQL feature that can be used to optimize the +Prepared statements are a GaussDB feature that can be used to optimize the performance of queries that are executed more than once. When a query is *prepared* by a call to :meth:`Connection.prepare`, the server parses, analyzes and compiles the query allowing to reuse that work once there is @@ -52,12 +52,6 @@ a need to run the same query again. during calls to the :meth:`~Connection.fetch`, :meth:`~Connection.fetchrow`, or :meth:`~Connection.fetchval` methods. -.. warning:: - - If you are using pgbouncer with ``pool_mode`` set to ``transaction`` or - ``statement``, prepared statements will not work correctly. See - :ref:`async_gaussdb-prepared-stmt-errors` for more information. - .. autoclass:: async_gaussdb.prepared_stmt.PreparedStatement() :members: @@ -117,9 +111,6 @@ See also the :meth:`Connection.transaction() ` function. -.. _savepoint: https://www.postgresql.org/docs/current/static/sql-savepoint.html - - .. autoclass:: async_gaussdb.transaction.Transaction() :members: @@ -282,7 +273,7 @@ items either by a numeric index or by a field name: .. class:: Record() - A read-only representation of PostgreSQL row. + A read-only representation of GaussDB row. .. describe:: len(r) diff --git a/docs/faq.rst b/docs/faq.rst index 47ce7481..056db6a2 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -10,7 +10,7 @@ Does async_gaussdb support DB-API? No. DB-API is a synchronous API, while async_gaussdb is based around an asynchronous I/O model. Thus, full drop-in compatibility with DB-API is not possible and we decided to design async_gaussdb API -in a way that is better aligned with PostgreSQL architecture and +in a way that is better aligned with GaussDB architecture and terminology. We will release a synchronous DB-API-compatible version of async_gaussdb at some point in the future. @@ -62,17 +62,7 @@ Why am I getting prepared statement errors? If you are getting intermittent ``prepared statement "__async_gaussdb_stmt_xx__" does not exist`` or ``prepared statement “__async_gaussdb_stmt_xx__” already exists`` errors, you are most likely not connecting to the -PostgreSQL server directly, but via -`pgbouncer `_. pgbouncer, when -in the ``"transaction"`` or ``"statement"`` pooling mode, does not support -prepared statements. You have several options: - -* if you are using pgbouncer only to reduce the cost of new connections - (as opposed to using pgbouncer for connection pooling from - a large number of clients in the interest of better scalability), - switch to the :ref:`connection pool ` - functionality provided by async_gaussdb, it is a much better option for this - purpose; +GaussDB server directly, but via * disable automatic use of prepared statements by passing ``statement_cache_size=0`` @@ -81,13 +71,13 @@ prepared statements. You have several options: (and, obviously, avoid the use of :meth:`Connection.prepare() `); -* switch pgbouncer's ``pool_mode`` to ``session``. -Why do I get ``PostgresSyntaxError`` when using ``expression IN $1``? + +Why do I get ``GaussDBSyntaxError`` when using ``expression IN $1``? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -``expression IN $1`` is not a valid PostgreSQL syntax. To check +``expression IN $1`` is not a valid GaussDB syntax. To check a value against a sequence use ``expression = any($1::mytype[])``, where ``mytype`` is the array element type. diff --git a/docs/installation.rst b/docs/installation.rst index fba48e7c..4f7a71ec 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -31,7 +31,7 @@ It is also possible to use GSSAPI on Windows: * `pip install gssapi` * Install `Kerberos for Windows `_. - * Set the ``gsslib`` parameter or the ``PGGSSLIB`` environment variable to + * Set the ``gsslib`` parameter or the ``GAUSSDBGSSLIB`` environment variable to `gssapi` when connecting. @@ -54,18 +54,18 @@ in the root of the source checkout: $ pip install -e . A debug build containing more runtime checks can be created by setting -the ``async_gaussdb_DEBUG`` environment variable when building: +the ``ASYNC_GAUSSDB_DEBUG`` environment variable when building: .. code-block:: bash - $ env async_gaussdb_DEBUG=1 pip install -e . + $ env ASYNC_GAUSSDB_DEBUG=1 pip install -e . Running tests ------------- -If you want to run tests you must have PostgreSQL installed. +If you want to run tests you must have GaussDB installed. To execute the testsuite run: diff --git a/docs/usage.rst b/docs/usage.rst index 30146d33..b87885fb 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -19,8 +19,8 @@ which provides methods to run queries and manage transactions. async def main(): # Establish a connection to an existing database named "test" - # as a "postgres" user. - conn = await async_gaussdb.connect('postgresql://postgres@localhost/test') + # as a "root" user. + conn = await async_gaussdb.connect('gaussdb://root@localhost/test') # Execute a statement to create a new table. await conn.execute(''' CREATE TABLE users( @@ -49,24 +49,24 @@ which provides methods to run queries and manage transactions. .. note:: - async_gaussdb uses the native PostgreSQL syntax for query arguments: ``$n``. + async_gaussdb uses the native GaussDB syntax for query arguments: ``$n``. Type Conversion --------------- -async_gaussdb automatically converts PostgreSQL types to the corresponding Python +async_gaussdb automatically converts GaussDB types to the corresponding Python types and vice versa. All standard data types are supported out of the box, including arrays, composite types, range types, enumerations and any combination of them. It is possible to supply codecs for non-standard types or override standard codecs. See :ref:`async_gaussdb-custom-codecs` for more information. -The table below shows the correspondence between PostgreSQL and Python types. +The table below shows the correspondence between GaussDB and Python types. +----------------------+-----------------------------------------------------+ -| PostgreSQL Type | Python Type | +| GaussDB Type | Python Type | +======================+=====================================================+ | ``anyarray`` | :class:`list ` | +----------------------+-----------------------------------------------------+ @@ -223,7 +223,7 @@ Example: complex types The example below shows how to configure async_gaussdb to encode and decode Python :class:`complex ` values to a custom composite -type in PostgreSQL. +type in GaussDB. .. code-block:: python @@ -370,7 +370,7 @@ be registered on a connection using :meth:`Connection.set_builtin_type_codec() asyncio.run(run()) -.. _hstore: https://www.postgresql.org/docs/current/static/hstore.html +.. _hstore Transactions @@ -404,7 +404,6 @@ For server-type type applications, that handle frequent requests and need the database connection for a short period time while handling a request, the use of a connection pool is recommended. async_gaussdb provides an advanced pool implementation, which eliminates the need to use an external connection -pooler such as PgBouncer. To create a connection pool, use the :func:`async_gaussdb.create_pool() ` function. @@ -440,7 +439,7 @@ Web service that computes the requested power of two. async def init_db(app): """Initialize a connection pool.""" app['pool'] = await async_gaussdb.create_pool(database='postgres', - user='postgres') + user='root') yield await app['pool'].close() diff --git a/tests/test__environment.py b/tests/test__environment.py index f7923842..c8d18d41 100644 --- a/tests/test__environment.py +++ b/tests/test__environment.py @@ -15,10 +15,10 @@ class TestEnvironment(tb.ConnectedTestCase): - @unittest.skipIf(not os.environ.get('PGVERSION'), - "environ[PGVERSION] is not set") + @unittest.skipIf(not os.environ.get('GAUSSDBVERSION'), + "environ[GAUSSDBVERSION] is not set") async def test_environment_server_version(self): - pgver = os.environ.get('PGVERSION') + pgver = os.environ.get('GAUSSDBVERSION') env_ver = async_gaussdb.serverversion.split_server_version_string(pgver) srv_ver = self.con.get_server_version() @@ -28,12 +28,12 @@ async def test_environment_server_version(self): pgver=pgver, maj=srv_ver.major, min=srv_ver.minor) ) - @unittest.skipIf(not os.environ.get('async_gaussdb_VERSION'), - "environ[async_gaussdb_VERSION] is not set") + @unittest.skipIf(not os.environ.get('ASYNC_GAUSSDB_VERSION'), + "environ[ASYNC_GAUSSDB_VERSION] is not set") @unittest.skipIf("dev" in async_gaussdb.__version__, "development version with git commit data") - async def test_environment_async_gaussdb_version(self): - apgver = os.environ.get('async_gaussdb_VERSION') + async def test_environment_ASYNC_GAUSSDB_VERSION(self): + apgver = os.environ.get('ASYNC_GAUSSDB_VERSION') self.assertEqual( async_gaussdb.__version__, apgver, 'Expecting async_gaussdb version {}, got {}.'.format( diff --git a/tests/test_adversity.py b/tests/test_adversity.py index bc9bff25..9d8f6213 100644 --- a/tests/test_adversity.py +++ b/tests/test_adversity.py @@ -14,7 +14,7 @@ from async_gaussdb import _testbase as tb -@unittest.skipIf(os.environ.get('PGHOST'), 'using remote cluster for testing') +@unittest.skipIf(os.environ.get('GAUSSDBHOST'), 'using remote cluster for testing') @unittest.skipIf( platform.system() == 'Windows', 'not compatible with ProactorEventLoop which is default in Python 3.8+') diff --git a/tests/test_codecs.py b/tests/test_codecs.py index 2ce30bb0..0cc0a918 100644 --- a/tests/test_codecs.py +++ b/tests/test_codecs.py @@ -17,7 +17,7 @@ import async_gaussdb from async_gaussdb import _testbase as tb -from async_gaussdb import cluster as pg_cluster +from async_gaussdb import cluster as gaussdb_cluster def _timezone(offset): @@ -2082,13 +2082,13 @@ async def test_array_with_custom_json_text_codec(self): ''') -@unittest.skipIf(os.environ.get('PGHOST'), 'using remote cluster for testing') +@unittest.skipIf(os.environ.get('GAUSSDBHOST'), 'using remote cluster for testing') class TestCodecsLargeOIDs(tb.ConnectedTestCase): LARGE_OID = 2147483648 @classmethod def setup_cluster(cls): - cls.cluster = cls.new_cluster(pg_cluster.TempCluster) + cls.cluster = cls.new_cluster(gaussdb_cluster.TempCluster) cls.cluster.reset_wal(oid=cls.LARGE_OID) cls.start_cluster(cls.cluster) diff --git a/tests/test_connect.py b/tests/test_connect.py index 3dc792ea..dd68be53 100644 --- a/tests/test_connect.py +++ b/tests/test_connect.py @@ -26,9 +26,9 @@ import async_gaussdb from async_gaussdb import _testbase as tb -from async_gaussdb import connection as pg_connection +from async_gaussdb import connection as gaussdb_connection from async_gaussdb import connect_utils -from async_gaussdb import cluster as pg_cluster +from async_gaussdb import cluster as gaussdb_cluster from async_gaussdb import exceptions from async_gaussdb.connect_utils import SSLMode from async_gaussdb.serverversion import split_server_version_string @@ -58,21 +58,21 @@ def mock_dot_gaussdb(*, ca=True, crl=False, client=False, protected=False): with tempfile.TemporaryDirectory() as temp_dir: home = pathlib.Path(temp_dir) - pg_home = home / '.gaussdb' - pg_home.mkdir() + gaussdb_home = home / '.gaussdb' + gaussdb_home.mkdir() if ca: - shutil.copyfile(SSL_CA_CERT_FILE, pg_home / 'root.crt') + shutil.copyfile(SSL_CA_CERT_FILE, gaussdb_home / 'root.crt') if crl: - shutil.copyfile(SSL_CA_CRL_FILE, pg_home / 'root.crl') + shutil.copyfile(SSL_CA_CRL_FILE, gaussdb_home / 'root.crl') if client: - shutil.copyfile(CLIENT_SSL_CERT_FILE, pg_home / 'gaussdb.crt') + shutil.copyfile(CLIENT_SSL_CERT_FILE, gaussdb_home / 'gaussdb.crt') if protected: shutil.copyfile( - CLIENT_SSL_PROTECTED_KEY_FILE, pg_home / 'gaussdb.key' + CLIENT_SSL_PROTECTED_KEY_FILE, gaussdb_home / 'gaussdb.key' ) else: shutil.copyfile( - CLIENT_SSL_KEY_FILE, pg_home / 'gaussdb.key' + CLIENT_SSL_KEY_FILE, gaussdb_home / 'gaussdb.key' ) with unittest.mock.patch( 'pathlib.Path.home', unittest.mock.Mock(return_value=home) @@ -424,7 +424,7 @@ def get_server_settings(cls): @classmethod def setup_cluster(cls): - cls.cluster = cls.new_cluster(pg_cluster.TempCluster) + cls.cluster = cls.new_cluster(gaussdb_cluster.TempCluster) cls.start_cluster( cls.cluster, server_settings=cls.get_server_settings()) @@ -478,11 +478,11 @@ class TestConnectParams(tb.TestCase): { 'name': 'all_env_default_ssl', 'env': { - 'PGUSER': 'user', - 'PGDATABASE': 'testdb', - 'PGPASSWORD': 'passw', - 'PGHOST': 'host', - 'PGPORT': '123' + 'GAUSSDBUSER': 'user', + 'GAUSSDBDATABASE': 'testdb', + 'GAUSSDBPASSWORD': 'passw', + 'GAUSSDBHOST': 'host', + 'GAUSSDBPORT': '123' }, 'result': ([('host', 123)], { 'user': 'user', @@ -496,11 +496,11 @@ class TestConnectParams(tb.TestCase): { 'name': 'params_override_env', 'env': { - 'PGUSER': 'user', - 'PGDATABASE': 'testdb', - 'PGPASSWORD': 'passw', - 'PGHOST': 'host', - 'PGPORT': '123' + 'GAUSSDBUSER': 'user', + 'GAUSSDBDATABASE': 'testdb', + 'GAUSSDBPASSWORD': 'passw', + 'GAUSSDBHOST': 'host', + 'GAUSSDBPORT': '123' }, 'host': 'host2', @@ -519,12 +519,12 @@ class TestConnectParams(tb.TestCase): { 'name': 'params_override_env_and_dsn', 'env': { - 'PGUSER': 'user', - 'PGDATABASE': 'testdb', - 'PGPASSWORD': 'passw', - 'PGHOST': 'host', - 'PGPORT': '123', - 'PGSSLMODE': 'allow' + 'GAUSSDBUSER': 'user', + 'GAUSSDBDATABASE': 'testdb', + 'GAUSSDBPASSWORD': 'passw', + 'GAUSSDBHOST': 'host', + 'GAUSSDBPORT': '123', + 'GAUSSDBSSLMODE': 'allow' }, 'dsn': 'gaussdb://user3:123123@localhost/abcdef', @@ -548,12 +548,12 @@ class TestConnectParams(tb.TestCase): { 'name': 'dsn_overrides_env_partially', 'env': { - 'PGUSER': 'user', - 'PGDATABASE': 'testdb', - 'PGPASSWORD': 'passw', - 'PGHOST': 'host', - 'PGPORT': '123', - 'PGSSLMODE': 'allow' + 'GAUSSDBUSER': 'user', + 'GAUSSDBDATABASE': 'testdb', + 'GAUSSDBPASSWORD': 'passw', + 'GAUSSDBHOST': 'host', + 'GAUSSDBPORT': '123', + 'GAUSSDBSSLMODE': 'allow' }, 'dsn': 'gaussdb://user3:123123@localhost:5555/abcdef', @@ -570,12 +570,12 @@ class TestConnectParams(tb.TestCase): { 'name': 'params_override_env_and_dsn_ssl_prefer', 'env': { - 'PGUSER': 'user', - 'PGDATABASE': 'testdb', - 'PGPASSWORD': 'passw', - 'PGHOST': 'host', - 'PGPORT': '123', - 'PGSSLMODE': 'prefer' + 'GAUSSDBUSER': 'user', + 'GAUSSDBDATABASE': 'testdb', + 'GAUSSDBPASSWORD': 'passw', + 'GAUSSDBHOST': 'host', + 'GAUSSDBPORT': '123', + 'GAUSSDBSSLMODE': 'prefer' }, 'dsn': 'gaussdb://user3:123123@localhost/abcdef', @@ -599,7 +599,7 @@ class TestConnectParams(tb.TestCase): { 'name': 'params_ssl_negotiation_dsn', 'env': { - 'PGSSLNEGOTIATION': 'gaussdb' + 'GAUSSDBSSLNEGOTIATION': 'gaussdb' }, 'dsn': 'gaussdb://u:p@localhost/d?sslnegotiation=direct', @@ -616,7 +616,7 @@ class TestConnectParams(tb.TestCase): { 'name': 'params_ssl_negotiation_env', 'env': { - 'PGSSLNEGOTIATION': 'direct' + 'GAUSSDBSSLNEGOTIATION': 'direct' }, 'dsn': 'gaussdb://u:p@localhost/d', @@ -633,7 +633,7 @@ class TestConnectParams(tb.TestCase): { 'name': 'params_ssl_negotiation_params', 'env': { - 'PGSSLNEGOTIATION': 'direct' + 'GAUSSDBSSLNEGOTIATION': 'direct' }, 'dsn': 'gaussdb://u:p@localhost/d', @@ -651,12 +651,12 @@ class TestConnectParams(tb.TestCase): { 'name': 'dsn_overrides_env_partially_ssl_prefer', 'env': { - 'PGUSER': 'user', - 'PGDATABASE': 'testdb', - 'PGPASSWORD': 'passw', - 'PGHOST': 'host', - 'PGPORT': '123', - 'PGSSLMODE': 'prefer' + 'GAUSSDBUSER': 'user', + 'GAUSSDBDATABASE': 'testdb', + 'GAUSSDBPASSWORD': 'passw', + 'GAUSSDBHOST': 'host', + 'GAUSSDBPORT': '123', + 'GAUSSDBSSLMODE': 'prefer' }, 'dsn': 'gaussdb://user3:123123@localhost:5555/abcdef', @@ -727,7 +727,7 @@ class TestConnectParams(tb.TestCase): 'name': 'target_session_attrs_3', 'dsn': 'gaussdb://user@host1:1111,host2:2222/db', 'env': { - 'PGTARGETSESSIONATTRS': 'read-only', + 'GAUSSDBTARGETSESSIONATTRS': 'read-only', }, 'result': ([('host1', 1111), ('host2', 2222)], { 'database': 'db', @@ -740,7 +740,7 @@ class TestConnectParams(tb.TestCase): 'name': 'krbsrvname', 'dsn': 'gaussdb://user@host/db?krbsrvname=srv_qs', 'env': { - 'PGKRBSRVNAME': 'srv_env', + 'GAUSSDBKRBSRVNAME': 'srv_env', }, 'result': ([('host', 5432)], { 'database': 'db', @@ -755,7 +755,7 @@ class TestConnectParams(tb.TestCase): 'dsn': 'gaussdb://user@host/db?krbsrvname=srv_qs', 'krbsrvname': 'srv_kws', 'env': { - 'PGKRBSRVNAME': 'srv_env', + 'GAUSSDBKRBSRVNAME': 'srv_env', }, 'result': ([('host', 5432)], { 'database': 'db', @@ -769,7 +769,7 @@ class TestConnectParams(tb.TestCase): 'name': 'krbsrvname_3', 'dsn': 'gaussdb://user@host/db', 'env': { - 'PGKRBSRVNAME': 'srv_env', + 'GAUSSDBKRBSRVNAME': 'srv_env', }, 'result': ([('host', 5432)], { 'database': 'db', @@ -783,7 +783,7 @@ class TestConnectParams(tb.TestCase): 'name': 'gsslib', 'dsn': f'gaussdb://user@host/db?gsslib={OTHER_GSSLIB}', 'env': { - 'PGGSSLIB': 'ignored', + 'GAUSSDBGSSLIB': 'ignored', }, 'result': ([('host', 5432)], { 'database': 'db', @@ -798,7 +798,7 @@ class TestConnectParams(tb.TestCase): 'dsn': 'gaussdb://user@host/db?gsslib=ignored', 'gsslib': OTHER_GSSLIB, 'env': { - 'PGGSSLIB': 'ignored', + 'GAUSSDBGSSLIB': 'ignored', }, 'result': ([('host', 5432)], { 'database': 'db', @@ -812,7 +812,7 @@ class TestConnectParams(tb.TestCase): 'name': 'gsslib_3', 'dsn': 'gaussdb://user@host/db', 'env': { - 'PGGSSLIB': OTHER_GSSLIB, + 'GAUSSDBGSSLIB': OTHER_GSSLIB, }, 'result': ([('host', 5432)], { 'database': 'db', @@ -877,8 +877,8 @@ class TestConnectParams(tb.TestCase): { 'name': 'dsn_combines_env_multi_host', 'env': { - 'PGHOST': 'host1:1111,host2:2222', - 'PGUSER': 'foo', + 'GAUSSDBHOST': 'host1:1111,host2:2222', + 'GAUSSDBUSER': 'foo', }, 'dsn': 'gaussdb:///db', 'result': ([('host1', 1111), ('host2', 2222)], { @@ -891,7 +891,7 @@ class TestConnectParams(tb.TestCase): { 'name': 'dsn_multi_host_combines_env', 'env': { - 'PGUSER': 'foo', + 'GAUSSDBUSER': 'foo', }, 'dsn': 'gaussdb:///db?host=host1:1111,host2:2222', 'result': ([('host1', 1111), ('host2', 2222)], { @@ -904,7 +904,7 @@ class TestConnectParams(tb.TestCase): { 'name': 'params_multi_host_dsn_env_mix', 'env': { - 'PGUSER': 'foo', + 'GAUSSDBUSER': 'foo', }, 'dsn': 'gaussdb:///db', 'host': ['host1', 'host2'], @@ -917,7 +917,7 @@ class TestConnectParams(tb.TestCase): { 'name': 'params_multi_host_dsn_env_mix_tuple', 'env': { - 'PGUSER': 'foo', + 'GAUSSDBUSER': 'foo', }, 'dsn': 'gaussdb:///db', 'host': ('host1', 'host2'), @@ -1087,13 +1087,13 @@ class TestConnectParams(tb.TestCase): { 'name': 'multi_host_single_port', 'dsn': 'gaussdb:///postgres?host=127.0.0.1,127.0.0.2&port=5432' - '&user=postgres', + '&user=root', 'result': ( [ ('127.0.0.1', 5432), ('127.0.0.2', 5432) ], { - 'user': 'postgres', + 'user': 'root', 'database': 'postgres', 'target_session_attrs': 'any', } @@ -1126,9 +1126,9 @@ def environ(self, **kwargs): def run_testcase(self, testcase): env = testcase.get('env', {}) - test_env = {'PGHOST': None, 'PGPORT': None, - 'PGUSER': None, 'PGPASSWORD': None, - 'PGDATABASE': None, 'PGSSLMODE': None} + test_env = {'GAUSSDBHOST': None, 'GAUSSDBPORT': None, + 'GAUSSDBUSER': None, 'GAUSSDBPASSWORD': None, + 'GAUSSDBDATABASE': None, 'GAUSSDBSSLMODE': None} test_env.update(env) dsn = testcase.get('dsn') @@ -1229,10 +1229,10 @@ def test_test_connect_params_environ(self): del os.environ[key] def test_test_connect_params_run_testcase(self): - with self.environ(PGPORT='777'): + with self.environ(GAUSSDBPORT='777'): self.run_testcase({ 'env': { - 'PGUSER': '__test__' + 'GAUSSDBUSER': '__test__' }, 'host': 'abc', 'result': ( @@ -1247,17 +1247,17 @@ def test_connect_params(self): for testcase in self.TESTS: self.run_testcase(testcase) - def test_connect_pgpass_regular(self): + def test_connect_gaussdbpass_regular(self): passfile = tempfile.NamedTemporaryFile('w+t', delete=False) passfile.write(textwrap.dedent(R''' - abc:*:*:user:password from pgpass for user@abc - localhost:*:*:*:password from pgpass for localhost - cde:5433:*:*:password from pgpass for cde:5433 + abc:*:*:user:password from gaussdbpass for user@abc + localhost:*:*:*:password from gaussdbpass for localhost + cde:5433:*:*:password from gaussdbpass for cde:5433 - *:*:*:testuser:password from pgpass for testuser - *:*:testdb:*:password from pgpass for testdb + *:*:*:testuser:password from gaussdbpass for testuser + *:*:testdb:*:password from gaussdbpass for testdb # comment - *:*:test\:db:test\\:password from pgpass with escapes + *:*:test\:db:test\\:password from gaussdbpass with escapes ''')) passfile.close() os.chmod(passfile.name, stat.S_IWUSR | stat.S_IRUSR) @@ -1266,7 +1266,7 @@ def test_connect_pgpass_regular(self): # passfile path in env self.run_testcase({ 'env': { - 'PGPASSFILE': passfile.name + 'GAUSSDBPASSFILE': passfile.name }, 'host': 'abc', 'user': 'user', @@ -1274,7 +1274,7 @@ def test_connect_pgpass_regular(self): 'result': ( [('abc', 5432)], { - 'password': 'password from pgpass for user@abc', + 'password': 'password from gaussdbpass for user@abc', 'user': 'user', 'database': 'db', 'target_session_attrs': 'any', @@ -1291,7 +1291,7 @@ def test_connect_pgpass_regular(self): 'result': ( [('abc', 5432)], { - 'password': 'password from pgpass for user@abc', + 'password': 'password from gaussdbpass for user@abc', 'user': 'user', 'database': 'db', 'target_session_attrs': 'any', @@ -1306,7 +1306,7 @@ def test_connect_pgpass_regular(self): 'result': ( [('abc', 5432)], { - 'password': 'password from pgpass for user@abc', + 'password': 'password from gaussdbpass for user@abc', 'user': 'user', 'database': 'db', 'target_session_attrs': 'any', @@ -1322,7 +1322,7 @@ def test_connect_pgpass_regular(self): 'result': ( [('localhost', 5432)], { - 'password': 'password from pgpass for localhost', + 'password': 'password from gaussdbpass for localhost', 'user': 'user', 'database': 'db', 'target_session_attrs': 'any', @@ -1340,7 +1340,7 @@ def test_connect_pgpass_regular(self): 'result': ( ['/tmp/.s.PGSQL.5432'], { - 'password': 'password from pgpass for localhost', + 'password': 'password from gaussdbpass for localhost', 'user': 'user', 'database': 'db', 'target_session_attrs': 'any', @@ -1358,7 +1358,7 @@ def test_connect_pgpass_regular(self): 'result': ( [('cde', 5433)], { - 'password': 'password from pgpass for cde:5433', + 'password': 'password from gaussdbpass for cde:5433', 'user': 'user', 'database': 'db', 'target_session_attrs': 'any', @@ -1375,7 +1375,7 @@ def test_connect_pgpass_regular(self): 'result': ( [('def', 5432)], { - 'password': 'password from pgpass for testuser', + 'password': 'password from gaussdbpass for testuser', 'user': 'testuser', 'database': 'db', 'target_session_attrs': 'any', @@ -1392,7 +1392,7 @@ def test_connect_pgpass_regular(self): 'result': ( [('efg', 5432)], { - 'password': 'password from pgpass for testdb', + 'password': 'password from gaussdbpass for testdb', 'user': 'user', 'database': 'testdb', 'target_session_attrs': 'any', @@ -1409,7 +1409,7 @@ def test_connect_pgpass_regular(self): 'result': ( [('fgh', 5432)], { - 'password': 'password from pgpass with escapes', + 'password': 'password from gaussdbpass with escapes', 'user': R'test\\', 'database': R'test\:db', 'target_session_attrs': 'any', @@ -1421,8 +1421,8 @@ def test_connect_pgpass_regular(self): os.unlink(passfile.name) @unittest.skipIf(_system == 'Windows', 'no mode checking on Windows') - def test_connect_pgpass_badness_mode(self): - # Verify that .pgpass permissions are checked + def test_connect_gaussdbpass_badness_mode(self): + # Verify that .gaussdbpass permissions are checked with tempfile.NamedTemporaryFile('w+t') as passfile: os.chmod(passfile.name, stat.S_IWUSR | stat.S_IRUSR | stat.S_IWGRP | stat.S_IRGRP) @@ -1445,8 +1445,8 @@ def test_connect_pgpass_badness_mode(self): ) }) - def test_connect_pgpass_badness_non_file(self): - # Verify warnings when .pgpass is not a file + def test_connect_gaussdbpass_badness_non_file(self): + # Verify warnings when .gaussdbpass is not a file with tempfile.TemporaryDirectory() as passfile: with self.assertWarnsRegex( UserWarning, @@ -1466,7 +1466,7 @@ def test_connect_pgpass_badness_non_file(self): ) }) - def test_connect_pgpass_nonexistent(self): + def test_connect_gaussdbpass_nonexistent(self): # nonexistent passfile is OK self.run_testcase({ 'host': 'abc', @@ -1484,7 +1484,7 @@ def test_connect_pgpass_nonexistent(self): }) @unittest.skipIf(_system == 'Windows', 'no mode checking on Windows') - def test_connect_pgpass_inaccessible_file(self): + def test_connect_gaussdbpass_inaccessible_file(self): with tempfile.NamedTemporaryFile('w+t') as passfile: os.chmod(passfile.name, stat.S_IWUSR) @@ -1505,7 +1505,7 @@ def test_connect_pgpass_inaccessible_file(self): }) @unittest.skipIf(_system == 'Windows', 'no mode checking on Windows') - def test_connect_pgpass_inaccessible_directory(self): + def test_connect_gaussdbpass_inaccessible_directory(self): with tempfile.TemporaryDirectory() as passdir: with tempfile.NamedTemporaryFile('w+t', dir=passdir) as passfile: os.chmod(passdir, stat.S_IWUSR) @@ -1545,7 +1545,7 @@ async def test_connect_args_validation(self): class TestConnection(tb.ConnectedTestCase): async def test_connection_isinstance(self): - self.assertTrue(isinstance(self.con, pg_connection.Connection)) + self.assertTrue(isinstance(self.con, gaussdb_connection.Connection)) self.assertTrue(isinstance(self.con, object)) self.assertFalse(isinstance(self.con, list)) @@ -1580,7 +1580,7 @@ def check(): with check(): await self.con.reset() - @unittest.skipIf(os.environ.get('PGHOST'), 'unmanaged cluster') + @unittest.skipIf(os.environ.get('GAUSSDBHOST'), 'unmanaged cluster') async def test_connection_ssl_to_no_ssl_server(self): ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) ssl_context.load_verify_locations(SSL_CA_CERT_FILE) @@ -1591,7 +1591,7 @@ async def test_connection_ssl_to_no_ssl_server(self): user='ssl_user', ssl=ssl_context) - @unittest.skipIf(os.environ.get('PGHOST'), 'unmanaged cluster') + @unittest.skipIf(os.environ.get('GAUSSDBHOST'), 'unmanaged cluster') async def test_connection_sslmode_no_ssl_server(self): async def verify_works(sslmode): con = None @@ -1638,12 +1638,12 @@ async def test_connection_implicit_host(self): user=conn_spec.get('user')) await con.close() - @unittest.skipIf(os.environ.get('PGHOST'), 'unmanaged cluster') + @unittest.skipIf(os.environ.get('GAUSSDBHOST'), 'unmanaged cluster') async def test_connection_no_home_dir(self): with mock_no_home_dir(): con = await self.connect( - dsn='postgresql://foo/', - user='postgres', + dsn='gaussdb://foo/', + user='root', database='postgres', host='localhost') await con.fetchval('SELECT 42') @@ -1651,8 +1651,8 @@ async def test_connection_no_home_dir(self): with mock_dev_null_home_dir(): con = await self.connect( - dsn='postgresql://foo/', - user='postgres', + dsn='gaussdb://foo/', + user='root', database='postgres', host='localhost') await con.fetchval('SELECT 42') @@ -1689,7 +1689,7 @@ def get_server_settings(cls): 'ssl_key_file': SSL_KEY_FILE, 'ssl_ca_file': CLIENT_CA_CERT_FILE, }) - if cls.cluster.get_pg_version() >= (12, 0): + if cls.cluster.get_gaussdb_version() >= (12, 0): conf['ssl_min_protocol_version'] = 'TLSv1.2' conf['ssl_max_protocol_version'] = 'TLSv1.2' @@ -1697,7 +1697,7 @@ def get_server_settings(cls): @classmethod def setup_cluster(cls): - cls.cluster = cls.new_cluster(pg_cluster.TempCluster) + cls.cluster = cls.new_cluster(gaussdb_cluster.TempCluster) cls.start_cluster( cls.cluster, server_settings=cls.get_server_settings()) @@ -1734,7 +1734,7 @@ def _add_hba_entry(self): raise NotImplementedError() -@unittest.skipIf(os.environ.get('PGHOST'), 'unmanaged cluster') +@unittest.skipIf(os.environ.get('GAUSSDBHOST'), 'unmanaged cluster') class TestSSLConnection(BaseTestSSLConnection): def _add_hba_entry(self): self.cluster.add_hba_entry( @@ -1889,7 +1889,7 @@ async def test_executemany_uvloop_ssl_issue_700(self): await con.close() async def test_tls_version(self): - if self.cluster.get_pg_version() < (12, 0): + if self.cluster.get_gaussdb_version() < (12, 0): self.skipTest("GaussDBSQL < 12 cannot set ssl protocol version") # XXX: uvloop artifact @@ -1940,7 +1940,7 @@ async def test_tls_version(self): self.loop.set_exception_handler(old_handler) -@unittest.skipIf(os.environ.get('PGHOST'), 'unmanaged cluster') +@unittest.skipIf(os.environ.get('GAUSSDBHOST'), 'unmanaged cluster') class TestClientSSLConnection(BaseTestSSLConnection): def _add_hba_entry(self): self.cluster.add_hba_entry( @@ -2013,19 +2013,19 @@ async def test_ssl_connection_client_auth_dsn(self): async def test_ssl_connection_client_auth_env(self): env = { - 'PGSSLROOTCERT': SSL_CA_CERT_FILE, - 'PGSSLCERT': CLIENT_SSL_CERT_FILE, - 'PGSSLKEY': CLIENT_SSL_KEY_FILE, + 'GAUSSDBSSLROOTCERT': SSL_CA_CERT_FILE, + 'GAUSSDBSSLCERT': CLIENT_SSL_CERT_FILE, + 'GAUSSDBSSLKEY': CLIENT_SSL_KEY_FILE, } dsn = 'gaussdb://ssl_user@localhost/postgres?sslmode=verify-full' with unittest.mock.patch.dict('os.environ', env): await self._test_works(dsn=dsn) - env['PGSSLKEY'] = CLIENT_SSL_PROTECTED_KEY_FILE + env['GAUSSDBSSLKEY'] = CLIENT_SSL_PROTECTED_KEY_FILE with unittest.mock.patch.dict('os.environ', env): await self._test_works(dsn=dsn + '&sslpassword=secRet') - async def test_ssl_connection_client_auth_dot_postgresql(self): + async def test_ssl_connection_client_auth_dot_gaussdb(self): dsn = 'gaussdb://ssl_user@localhost/postgres?sslmode=verify-full' with mock_dot_gaussdb(client=True): await self._test_works(dsn=dsn) @@ -2033,7 +2033,7 @@ async def test_ssl_connection_client_auth_dot_postgresql(self): await self._test_works(dsn=dsn + '&sslpassword=secRet') -@unittest.skipIf(os.environ.get('PGHOST'), 'unmanaged cluster') +@unittest.skipIf(os.environ.get('GAUSSDBHOST'), 'unmanaged cluster') class TestNoSSLConnection(BaseTestSSLConnection): def _add_hba_entry(self): self.cluster.add_hba_entry( @@ -2201,7 +2201,7 @@ async def test_target_server_attribute_port(self): await self._run_connection_test( connect, target_attr, expected_port ) - if self.master_cluster.get_pg_version()[0] < 14: + if self.master_cluster.get_gaussdb_version()[0] < 14: self.skipTest("gaussdb<14 does not support these features") tests = [ (self.connect_primary, 'read-write', master_port), @@ -2223,7 +2223,7 @@ async def test_target_attribute_not_matched(self): with self.assertRaises(exceptions.TargetServerAttributeNotMatched): await connect(target_session_attrs=target_attr) - if self.master_cluster.get_pg_version()[0] < 14: + if self.master_cluster.get_gaussdb_version()[0] < 14: self.skipTest("gaussdb<14 does not support these features") tests = [ (self.connect_standby, 'read-write'), diff --git a/tests/test_listeners.py b/tests/test_listeners.py index 158abcb0..4811e90a 100644 --- a/tests/test_listeners.py +++ b/tests/test_listeners.py @@ -130,13 +130,13 @@ async def test_log_listener_01(self): q2 = asyncio.Queue() def notice_callb(con, message): - # Message fields depend on PG version, hide some values. + # Message fields depend on GaussDB version, hide some values. dct = message.as_dict() del dct['server_source_line'] q1.put_nowait((con, type(message), dct)) async def async_notice_callb(con, message): - # Message fields depend on PG version, hide some values. + # Message fields depend on GaussDB version, hide some values. dct = message.as_dict() del dct['server_source_line'] q2.put_nowait((con, type(message), dct)) @@ -281,7 +281,7 @@ async def raise_message(level, code): """.format(level, code)) def notice_callb(con, message): - # Message fields depend on PG version, hide some values. + # Message fields depend on GaussDB version, hide some values. q1.put_nowait(message) self.con.add_log_listener(notice_callb) @@ -313,7 +313,7 @@ def listener1(*args): con.add_log_listener(listener1) -@unittest.skipIf(os.environ.get('PGHOST'), 'using remote cluster for testing') +@unittest.skipIf(os.environ.get('GAUSSDBHOST'), 'using remote cluster for testing') @unittest.skipIf( platform.system() == 'Windows', 'not compatible with ProactorEventLoop which is default in Python 3.8+') diff --git a/tests/test_pool.py b/tests/test_pool.py index 5d3c7f10..1332e4db 100644 --- a/tests/test_pool.py +++ b/tests/test_pool.py @@ -17,9 +17,9 @@ import async_gaussdb from async_gaussdb import _testbase as tb -from async_gaussdb import connection as pg_connection -from async_gaussdb import pool as pg_pool -from async_gaussdb import cluster as pg_cluster +from async_gaussdb import connection as gaussdb_connection +from async_gaussdb import pool as gaussdb_pool +from async_gaussdb import cluster as gaussdb_cluster _system = platform.uname().system @@ -27,14 +27,14 @@ POOL_NOMINAL_TIMEOUT = 0.5 -class SlowResetConnection(pg_connection.Connection): +class SlowResetConnection(gaussdb_connection.Connection): """Connection class to simulate races with Connection.reset().""" async def reset(self, *, timeout=None): await asyncio.sleep(0.2) return await super().reset(timeout=timeout) -class SlowCancelConnection(pg_connection.Connection): +class SlowCancelConnection(gaussdb_connection.Connection): """Connection class to simulate races with Connection._cancel().""" async def _cancel(self, waiter): await asyncio.sleep(0.2) @@ -144,7 +144,7 @@ async def test_pool_07(self): async def connect(*args, **kwargs): nonlocal connect_called connect_called += 1 - return await pg_connection.connect(*args, **kwargs) + return await gaussdb_connection.connect(*args, **kwargs) async def setup(con): nonlocal setup_called @@ -292,7 +292,7 @@ async def test_pool_12(self): min_size=1, max_size=1) async with pool.acquire() as con: - self.assertTrue(isinstance(con, pg_connection.Connection)) + self.assertTrue(isinstance(con, gaussdb_connection.Connection)) self.assertFalse(isinstance(con, list)) await pool.close() @@ -307,7 +307,7 @@ async def test_pool_13(self): self.assertIn( str(inspect.signature(con.execute))[1:], - str(inspect.signature(pg_connection.Connection.execute))) + str(inspect.signature(gaussdb_connection.Connection.execute))) await pool.close() @@ -1006,12 +1006,12 @@ async def worker(): await pool.release(conn) -@unittest.skipIf(os.environ.get('PGHOST'), 'unmanaged cluster') +@unittest.skipIf(os.environ.get('GAUSSDBHOST'), 'unmanaged cluster') class TestPoolReconnectWithTargetSessionAttrs(tb.ClusterTestCase): @classmethod def setup_cluster(cls): - cls.cluster = cls.new_cluster(pg_cluster.TempCluster) + cls.cluster = cls.new_cluster(gaussdb_cluster.TempCluster) cls.start_cluster(cls.cluster) async def simulate_cluster_recovery_mode(self): @@ -1033,7 +1033,7 @@ async def simulate_cluster_recovery_mode(self): ) async def test_full_reconnect_on_node_change_role(self): - if self.cluster.get_pg_version() < (12, 0): + if self.cluster.get_gaussdb_version() < (12, 0): self.skipTest("GaussDBSQL < 12 cannot support standby.signal") return @@ -1070,18 +1070,18 @@ async def test_full_reconnect_on_node_change_role(self): ) -@unittest.skipIf(os.environ.get('PGHOST'), 'using remote cluster for testing') +@unittest.skipIf(os.environ.get('GAUSSDBHOST'), 'using remote cluster for testing') class TestHotStandby(tb.HotStandbyTestCase): def create_pool(self, **kwargs): conn_spec = self.standby_cluster.get_connection_spec() conn_spec.update(kwargs) - return pg_pool.create_pool(loop=self.loop, **conn_spec) + return gaussdb_pool.create_pool(loop=self.loop, **conn_spec) async def test_standby_pool_01(self): for n in {1, 3, 5, 10, 20, 100}: with self.subTest(tasksnum=n): pool = await self.create_pool( - database='postgres', user='postgres', + database='postgres', user='root', min_size=5, max_size=10) async def worker(): @@ -1095,7 +1095,7 @@ async def worker(): async def test_standby_cursors(self): con = await self.standby_cluster.connect( - database='postgres', user='postgres', loop=self.loop) + database='postgres', user='root', loop=self.loop) try: async with con.transaction(): diff --git a/tests/test_prepare.py b/tests/test_prepare.py index 383593cb..d58bd221 100644 --- a/tests/test_prepare.py +++ b/tests/test_prepare.py @@ -572,7 +572,7 @@ async def test_prepare_30_invalid_arg_count(self): 'the server expects 0 arguments for this query, 1 was passed'): await self.con.fetchval('SELECT 1', 1) - async def test_prepare_31_pgbouncer_note(self): + async def test_prepare_31_gsbouncer_note(self): try: await self.con.execute(""" DO $$ BEGIN diff --git a/tests/test_timeout.py b/tests/test_timeout.py index 292d8041..84477d79 100644 --- a/tests/test_timeout.py +++ b/tests/test_timeout.py @@ -8,7 +8,7 @@ import asyncio import async_gaussdb -from async_gaussdb import connection as pg_connection +from async_gaussdb import connection as gaussdb_connection from async_gaussdb import _testbase as tb @@ -136,7 +136,7 @@ async def test_command_timeout_01(self): self.assertEqual(await self.con.fetch('select 1'), [(1,)]) -class SlowPrepareConnection(pg_connection.Connection): +class SlowPrepareConnection(gaussdb_connection.Connection): """Connection class to test timeouts.""" async def _get_statement(self, query, timeout, **kwargs): await asyncio.sleep(0.3) diff --git a/tools/generate_type_map.py b/tools/generate_type_map.py index 21f8af20..16ecb08b 100755 --- a/tools/generate_type_map.py +++ b/tools/generate_type_map.py @@ -44,9 +44,9 @@ async def runner(args): - conn = await async_gaussdb.connect(host=args.pghost, - port=args.pgport, - user=args.pguser) + conn = await async_gaussdb.connect(host=args.gaussdbhost, + port=args.gaussdbport, + user=args.gaussdbuser) buf = ( '# Copyright (C) 2016-present the asyncpg authors and contributors\n' @@ -115,13 +115,13 @@ def main(): parser = argparse.ArgumentParser( description='generate protocol/pgtypes.pxi from pg_catalog.pg_types') parser.add_argument( - '--pghost', type=str, default='127.0.0.1', + '--gaussdbhost', type=str, default='127.0.0.1', help='GaussDBSQL server host') parser.add_argument( - '--pgport', type=int, default=5432, + '--gaussdbport', type=int, default=5432, help='GaussDBSQL server port') parser.add_argument( - '--pguser', type=str, default='postgres', + '--gaussdbuser', type=str, default='root', help='GaussDBSQL server user') args = parser.parse_args() From 53d19d2ef18c8416763e84c10d86e2fe764ebfdd Mon Sep 17 00:00:00 2001 From: zhanghaitao3 <1085912315@qq.com> Date: Tue, 2 Dec 2025 02:17:05 +0800 Subject: [PATCH 3/3] Code refactoring, all content except Cpython --- .github/workflows/install-postgres.sh | 62 ------------------------- async_gaussdb/protocol/codecs/array.pyx | 12 ++--- 2 files changed, 6 insertions(+), 68 deletions(-) delete mode 100755 .github/workflows/install-postgres.sh diff --git a/.github/workflows/install-postgres.sh b/.github/workflows/install-postgres.sh deleted file mode 100755 index 9b7cb0c9..00000000 --- a/.github/workflows/install-postgres.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/bash - -set -Eexuo pipefail -shopt -s nullglob - -if [[ $OSTYPE == linux* ]]; then - GAUSSDBVERSION=${PGVERSION:-12} - - if [ -e /etc/os-release ]; then - source /etc/os-release - elif [ -e /etc/centos-release ]; then - ID="centos" - VERSION_ID=$(cat /etc/centos-release | cut -f3 -d' ' | cut -f1 -d.) - else - echo "install-postgres.sh: cannot determine which Linux distro this is" >&2 - exit 1 - fi - - if [ "${ID}" = "debian" -o "${ID}" = "ubuntu" ]; then - export DEBIAN_FRONTEND=noninteractive - - apt-get install -y --no-install-recommends curl gnupg ca-certificates - curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - - mkdir -p /etc/apt/sources.list.d/ - echo "deb https://apt.postgresql.org/pub/repos/apt/ ${VERSION_CODENAME}-pgdg main" \ - >> /etc/apt/sources.list.d/pgdg.list - apt-get update - apt-get install -y --no-install-recommends \ - "postgresql-${PGVERSION}" \ - "postgresql-contrib-${PGVERSION}" - elif [ "${ID}" = "almalinux" ]; then - yum install -y \ - "postgresql-server" \ - "postgresql-devel" \ - "postgresql-contrib" - elif [ "${ID}" = "centos" ]; then - el="EL-${VERSION_ID%.*}-$(arch)" - baseurl="https://download.postgresql.org/pub/repos/yum/reporpms" - yum install -y "${baseurl}/${el}/pgdg-redhat-repo-latest.noarch.rpm" - if [ ${VERSION_ID%.*} -ge 8 ]; then - dnf -qy module disable postgresql - fi - yum install -y \ - "postgresql${PGVERSION}-server" \ - "postgresql${PGVERSION}-contrib" - ln -s "/usr/pgsql-${PGVERSION}/bin/pg_config" "/usr/local/bin/pg_config" - elif [ "${ID}" = "alpine" ]; then - apk add shadow postgresql postgresql-dev postgresql-contrib - else - echo "install-postgres.sh: unsupported Linux distro: ${distro}" >&2 - exit 1 - fi - - useradd -m -s /bin/bash apgtest - -elif [[ $OSTYPE == darwin* ]]; then - brew install postgresql - -else - echo "install-postgres.sh: unsupported OS: ${OSTYPE}" >&2 - exit 1 -fi diff --git a/async_gaussdb/protocol/codecs/array.pyx b/async_gaussdb/protocol/codecs/array.pyx index 85dfcdf9..8d7219c1 100644 --- a/async_gaussdb/protocol/codecs/array.pyx +++ b/async_gaussdb/protocol/codecs/array.pyx @@ -419,7 +419,7 @@ cdef textarray_decode(ConnectionSettings settings, FRBuffer *buf, # Make a copy of array data since we will be mutating it for # the purposes of element decoding. - s = gaussdbproto.text_decode(settings, buf) + s = pgproto.text_decode(settings, buf) array_text = cpythonx.PyUnicode_AsUCS4Copy(s) try: @@ -648,7 +648,7 @@ cdef _textarray_decode(ConnectionSettings settings, # Prepare the element buffer and call the text decoder # for the element type. - gaussdbproto.as_pg_string_and_size( + pgproto.as_pg_string_and_size( settings, item_text, &pg_item_str, &pg_item_len) frb_init(&item_buf, pg_item_str, pg_item_len) item = decoder(settings, &item_buf, decoder_arg) @@ -822,12 +822,12 @@ cdef _infer_array_dims(const Py_UCS4 *array_text, cdef uint4_encode_ex(ConnectionSettings settings, WriteBuffer buf, object obj, const void *arg): - return gaussdbproto.uint4_encode(settings, buf, obj) + return pgproto.uint4_encode(settings, buf, obj) cdef uint4_decode_ex(ConnectionSettings settings, FRBuffer *buf, const void *arg): - return gaussdbproto.uint4_decode(settings, buf) + return pgproto.uint4_decode(settings, buf) cdef arrayoid_encode(ConnectionSettings settings, WriteBuffer buf, items): @@ -841,12 +841,12 @@ cdef arrayoid_decode(ConnectionSettings settings, FRBuffer *buf): cdef text_encode_ex(ConnectionSettings settings, WriteBuffer buf, object obj, const void *arg): - return gaussdbproto.text_encode(settings, buf, obj) + return pgproto.text_encode(settings, buf, obj) cdef text_decode_ex(ConnectionSettings settings, FRBuffer *buf, const void *arg): - return gaussdbproto.text_decode(settings, buf) + return pgproto.text_decode(settings, buf) cdef arraytext_encode(ConnectionSettings settings, WriteBuffer buf, items):