Skip to content

Commit 2401474

Browse files
A support of Python v3.8 (#238)
* A support of Python 3.8 [typing] Python 3.8 does not support tuple[...], list[...], set[...] and so on. We will use the analogues from typing package: typing.Tuple[...], typing.List[...] and typing.Set[...]. * [CI] Jobs for testing with python 3.8.0, 3.8.latest, 3.9.latest, 3.10.latest and 3.11.latest [std2-all][alpine] are added
1 parent da2c493 commit 2401474

File tree

9 files changed

+199
-22
lines changed

9 files changed

+199
-22
lines changed

.travis.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ notifications:
1919
on_failure: always
2020

2121
env:
22+
- TEST_PLATFORM=std2-all PYTHON_VERSION=3.8.0 PG_VERSION=17
23+
- TEST_PLATFORM=std2-all PYTHON_VERSION=3.8 PG_VERSION=17
24+
- TEST_PLATFORM=std2-all PYTHON_VERSION=3.9 PG_VERSION=17
25+
- TEST_PLATFORM=std2-all PYTHON_VERSION=3.10 PG_VERSION=17
26+
- TEST_PLATFORM=std2-all PYTHON_VERSION=3.11 PG_VERSION=17
2227
- TEST_PLATFORM=std PYTHON_VERSION=3 PG_VERSION=16
2328
- TEST_PLATFORM=std PYTHON_VERSION=3 PG_VERSION=15
2429
- TEST_PLATFORM=std PYTHON_VERSION=3 PG_VERSION=14

Dockerfile--std2-all.tmpl

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
ARG PG_VERSION
2+
ARG PYTHON_VERSION
3+
4+
# --------------------------------------------- base1
5+
FROM postgres:${PG_VERSION}-alpine as base1
6+
7+
# --------------------------------------------- base2_with_python-3
8+
FROM base1 as base2_with_python-3
9+
RUN apk add --no-cache curl python3 python3-dev build-base musl-dev linux-headers
10+
11+
# For pyenv
12+
RUN apk add patch
13+
RUN apk add git
14+
RUN apk add xz-dev
15+
RUN apk add zip
16+
RUN apk add zlib-dev
17+
RUN apk add libffi-dev
18+
RUN apk add readline-dev
19+
RUN apk add openssl openssl-dev
20+
RUN apk add sqlite-dev
21+
RUN apk add bzip2-dev
22+
23+
# --------------------------------------------- base3_with_python-3.8.0
24+
FROM base2_with_python-3 as base3_with_python-3.8.0
25+
ENV PYTHON_VERSION=3.8.0
26+
27+
# --------------------------------------------- base3_with_python-3.8
28+
FROM base2_with_python-3 as base3_with_python-3.8
29+
ENV PYTHON_VERSION=3.8
30+
31+
# --------------------------------------------- base3_with_python-3.9
32+
FROM base2_with_python-3 as base3_with_python-3.9
33+
ENV PYTHON_VERSION=3.9
34+
35+
# --------------------------------------------- base3_with_python-3.10
36+
FROM base2_with_python-3 as base3_with_python-3.10
37+
ENV PYTHON_VERSION=3.10
38+
39+
# --------------------------------------------- base3_with_python-3.11
40+
FROM base2_with_python-3 as base3_with_python-3.11
41+
ENV PYTHON_VERSION=3.11
42+
43+
# --------------------------------------------- final
44+
FROM base3_with_python-${PYTHON_VERSION} as final
45+
46+
#RUN apk add --no-cache mc
47+
48+
# Full version of "ps" command
49+
RUN apk add --no-cache procps
50+
51+
RUN apk add --no-cache openssh
52+
RUN apk add --no-cache sudo
53+
54+
ENV LANG=C.UTF-8
55+
56+
RUN addgroup -S sudo
57+
RUN adduser postgres sudo
58+
59+
EXPOSE 22
60+
RUN ssh-keygen -A
61+
62+
ADD . /pg/testgres
63+
WORKDIR /pg/testgres
64+
RUN chown -R postgres:postgres /pg
65+
66+
# It allows to use sudo without password
67+
RUN sh -c "echo \"postgres ALL=(ALL:ALL) NOPASSWD:ALL\"">>/etc/sudoers
68+
69+
# THIS CMD IS NEEDED TO CONNECT THROUGH SSH WITHOUT PASSWORD
70+
RUN sh -c "echo "postgres:*" | chpasswd -e"
71+
72+
USER postgres
73+
74+
RUN curl https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer | bash
75+
76+
RUN ~/.pyenv/bin/pyenv install ${PYTHON_VERSION}
77+
78+
# THIS CMD IS NEEDED TO CONNECT THROUGH SSH WITHOUT PASSWORD
79+
RUN chmod 700 ~/
80+
81+
RUN mkdir -p ~/.ssh
82+
#RUN chmod 700 ~/.ssh
83+
84+
ENTRYPOINT sh -c " \
85+
set -eux; \
86+
echo HELLO FROM ENTRYPOINT; \
87+
echo HOME DIR IS [`realpath ~/`]; \
88+
ssh-keygen -t rsa -f ~/.ssh/id_rsa -q -N ''; \
89+
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys; \
90+
chmod 600 ~/.ssh/authorized_keys; \
91+
ls -la ~/.ssh/; \
92+
sudo /usr/sbin/sshd; \
93+
ssh-keyscan -H localhost >> ~/.ssh/known_hosts; \
94+
ssh-keyscan -H 127.0.0.1 >> ~/.ssh/known_hosts; \
95+
export PATH=\"~/.pyenv/bin:$PATH\"; \
96+
TEST_FILTER=\"\" bash run_tests2.sh;"

run_tests2.sh

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#!/usr/bin/env bash
2+
3+
# Copyright (c) 2017-2025 Postgres Professional
4+
5+
set -eux
6+
7+
eval "$(pyenv init -)"
8+
eval "$(pyenv virtualenv-init -)"
9+
10+
pyenv virtualenv --force ${PYTHON_VERSION} cur
11+
pyenv activate cur
12+
13+
if [ -z ${TEST_FILTER+x} ]; \
14+
then export TEST_FILTER="TestTestgresLocal or (TestTestgresCommon and (not remote))"; \
15+
fi
16+
17+
# fail early
18+
echo check that pg_config is in PATH
19+
command -v pg_config
20+
21+
# prepare python environment
22+
VENV_PATH="/tmp/testgres_venv"
23+
rm -rf $VENV_PATH
24+
python -m venv "${VENV_PATH}"
25+
export VIRTUAL_ENV_DISABLE_PROMPT=1
26+
source "${VENV_PATH}/bin/activate"
27+
pip install coverage flake8 psutil Sphinx pytest pytest-xdist psycopg2 six psutil
28+
29+
# install testgres' dependencies
30+
export PYTHONPATH=$(pwd)
31+
# $PIP install .
32+
33+
# test code quality
34+
flake8 .
35+
36+
37+
# remove existing coverage file
38+
export COVERAGE_FILE=.coverage
39+
rm -f $COVERAGE_FILE
40+
41+
42+
# run tests (PATH)
43+
time coverage run -a -m pytest -l -v -n 4 -k "${TEST_FILTER}"
44+
45+
46+
# run tests (PG_BIN)
47+
PG_BIN=$(pg_config --bindir) \
48+
time coverage run -a -m pytest -l -v -n 4 -k "${TEST_FILTER}"
49+
50+
51+
# run tests (PG_CONFIG)
52+
PG_CONFIG=$(pg_config --bindir)/pg_config \
53+
time coverage run -a -m pytest -l -v -n 4 -k "${TEST_FILTER}"
54+
55+
56+
# show coverage
57+
coverage report
58+
59+
# build documentation
60+
cd docs
61+
make html
62+
cd ..
63+
64+
# attempt to fix codecov
65+
set +eux
66+
67+
# send coverage stats to Codecov
68+
bash <(curl -s https://codecov.io/bash)

testgres/operations/remote_ops.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import tempfile
66
import io
77
import logging
8+
import typing
89

910
from ..exceptions import ExecUtilException
1011
from ..exceptions import InvalidOperationException
@@ -669,8 +670,8 @@ def _is_port_free__process_1(error: str) -> bool:
669670
return True
670671

671672
@staticmethod
672-
def _make_exec_env_list() -> list[str]:
673-
result = list[str]()
673+
def _make_exec_env_list() -> typing.List[str]:
674+
result: typing.List[str] = list()
674675
for envvar in os.environ.items():
675676
if not __class__._does_put_envvar_into_exec_cmd(envvar[0]):
676677
continue

testgres/port_manager.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import threading
88
import random
9+
import typing
910

1011

1112
class PortManager:
@@ -50,16 +51,16 @@ class PortManager__Generic(PortManager):
5051
_os_ops: OsOperations
5152
_guard: object
5253
# TODO: is there better to use bitmap fot _available_ports?
53-
_available_ports: set[int]
54-
_reserved_ports: set[int]
54+
_available_ports: typing.Set[int]
55+
_reserved_ports: typing.Set[int]
5556

5657
def __init__(self, os_ops: OsOperations):
5758
assert os_ops is not None
5859
assert isinstance(os_ops, OsOperations)
5960
self._os_ops = os_ops
6061
self._guard = threading.Lock()
61-
self._available_ports = set[int](range(1024, 65535))
62-
self._reserved_ports = set[int]()
62+
self._available_ports: typing.Set[int] = set(range(1024, 65535))
63+
self._reserved_ports: typing.Set[int] = set()
6364

6465
def reserve_port(self) -> int:
6566
assert self._guard is not None

tests/conftest.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ class TestConfigPropNames:
2626
TEST_CFG__LOG_DIR = "TEST_CFG__LOG_DIR"
2727

2828

29+
# /////////////////////////////////////////////////////////////////////////////
30+
31+
T_TUPLE__str_int = typing.Tuple[str, int]
32+
2933
# /////////////////////////////////////////////////////////////////////////////
3034
# TestStartupData__Helper
3135

@@ -110,11 +114,11 @@ class TEST_PROCESS_STATS:
110114
cUnexpectedTests: int = 0
111115
cAchtungTests: int = 0
112116

113-
FailedTests = list[str, int]()
114-
XFailedTests = list[str, int]()
115-
NotXFailedTests = list[str]()
116-
WarningTests = list[str, int]()
117-
AchtungTests = list[str]()
117+
FailedTests: typing.List[T_TUPLE__str_int] = list()
118+
XFailedTests: typing.List[T_TUPLE__str_int] = list()
119+
NotXFailedTests: typing.List[str] = list()
120+
WarningTests: typing.List[T_TUPLE__str_int] = list()
121+
AchtungTests: typing.List[str] = list()
118122

119123
cTotalDuration: datetime.timedelta = datetime.timedelta()
120124

@@ -769,7 +773,7 @@ def helper__calc_W(n: int) -> int:
769773

770774

771775
# ------------------------------------------------------------------------
772-
def helper__print_test_list(tests: list[str]) -> None:
776+
def helper__print_test_list(tests: typing.List[str]) -> None:
773777
assert type(tests) == list # noqa: E721
774778

775779
assert helper__calc_W(9) == 1
@@ -796,7 +800,7 @@ def helper__print_test_list(tests: list[str]) -> None:
796800

797801

798802
# ------------------------------------------------------------------------
799-
def helper__print_test_list2(tests: list[str, int]) -> None:
803+
def helper__print_test_list2(tests: typing.List[T_TUPLE__str_int]) -> None:
800804
assert type(tests) == list # noqa: E721
801805

802806
assert helper__calc_W(9) == 1
@@ -843,7 +847,7 @@ def LOCAL__print_line1_with_header(header: str):
843847
assert header != ""
844848
logging.info(C_LINE1 + " [" + header + "]")
845849

846-
def LOCAL__print_test_list(header: str, test_count: int, test_list: list[str]):
850+
def LOCAL__print_test_list(header: str, test_count: int, test_list: typing.List[str]):
847851
assert type(header) == str # noqa: E721
848852
assert type(test_count) == int # noqa: E721
849853
assert type(test_list) == list # noqa: E721
@@ -858,7 +862,7 @@ def LOCAL__print_test_list(header: str, test_count: int, test_list: list[str]):
858862
logging.info("")
859863

860864
def LOCAL__print_test_list2(
861-
header: str, test_count: int, test_list: list[str, int]
865+
header: str, test_count: int, test_list: typing.List[T_TUPLE__str_int]
862866
):
863867
assert type(header) == str # noqa: E721
864868
assert type(test_count) == int # noqa: E721

tests/test_os_ops_common.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@
1212
import logging
1313
import socket
1414
import threading
15+
import typing
1516

1617
from ..testgres import InvalidOperationException
1718
from ..testgres import ExecUtilException
1819

1920

2021
class TestOsOpsCommon:
21-
sm_os_ops_descrs: list[OsOpsDescr] = [
22+
sm_os_ops_descrs: typing.List[OsOpsDescr] = [
2223
OsOpsDescrs.sm_local_os_ops_descr,
2324
OsOpsDescrs.sm_remote_os_ops_descr
2425
]

tests/test_testgres_common.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def removing(os_ops: OsOperations, f):
5656

5757

5858
class TestTestgresCommon:
59-
sm_node_svcs: list[PostgresNodeService] = [
59+
sm_node_svcs: typing.List[PostgresNodeService] = [
6060
PostgresNodeServices.sm_local,
6161
PostgresNodeServices.sm_local2,
6262
PostgresNodeServices.sm_remote,
@@ -315,8 +315,8 @@ def test_child_pids(self, node_svc: PostgresNodeService):
315315

316316
def LOCAL__test_auxiliary_pids(
317317
node: PostgresNode,
318-
expectedTypes: list[ProcessType]
319-
) -> list[ProcessType]:
318+
expectedTypes: typing.List[ProcessType]
319+
) -> typing.List[ProcessType]:
320320
# returns list of the absence processes
321321
assert node is not None
322322
assert type(node) == PostgresNode # noqa: E721
@@ -327,15 +327,15 @@ def LOCAL__test_auxiliary_pids(
327327
assert pids is not None # noqa: E721
328328
assert type(pids) == dict # noqa: E721
329329

330-
result = list[ProcessType]()
330+
result: typing.List[ProcessType] = list()
331331
for ptype in expectedTypes:
332332
if not (ptype in pids):
333333
result.append(ptype)
334334
return result
335335

336336
def LOCAL__check_auxiliary_pids__multiple_attempts(
337337
node: PostgresNode,
338-
expectedTypes: list[ProcessType]):
338+
expectedTypes: typing.List[ProcessType]):
339339
assert node is not None
340340
assert type(node) == PostgresNode # noqa: E721
341341
assert expectedTypes is not None

tests/test_utils.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77
from ..testgres import scoped_config
88

99
import pytest
10+
import typing
1011

1112

1213
class TestUtils:
13-
sm_os_ops_descrs: list[OsOpsDescr] = [
14+
sm_os_ops_descrs: typing.List[OsOpsDescr] = [
1415
OsOpsDescrs.sm_local_os_ops_descr,
1516
OsOpsDescrs.sm_remote_os_ops_descr
1617
]

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy