11from __future__ import annotations
22
3+ import contextlib
34import os
45import sys
6+ from dataclasses import dataclass
57from pathlib import Path
68from typing import TYPE_CHECKING
79
810import oracledb
911import pytest
1012
13+ from pytest_databases ._service import DockerService
1114from pytest_databases .docker import DockerServiceRegistry
1215from pytest_databases .helpers import simple_string_hash
16+ from pytest_databases .types import ServiceContainer
1317
1418if TYPE_CHECKING :
1519 from collections .abc import Generator
@@ -35,223 +39,113 @@ def oracle_responsive(host: str, port: int, service_name: str, user: str, passwo
3539 return False
3640
3741
38- @pytest .fixture (scope = "session" )
39- def oracle_compose_project_name () -> str :
40- return os .environ .get ("COMPOSE_PROJECT_NAME" , COMPOSE_PROJECT_NAME )
41-
42-
43- @pytest .fixture (autouse = False , scope = "session" )
44- def oracle_docker_services (
45- oracle_compose_project_name : str , worker_id : str = "main"
46- ) -> Generator [DockerServiceRegistry , None , None ]:
47- if os .getenv ("GITHUB_ACTIONS" ) == "true" and sys .platform != "linux" :
48- pytest .skip ("Docker not available on this platform" )
49-
50- with DockerServiceRegistry (worker_id , compose_project_name = oracle_compose_project_name ) as registry :
51- yield registry
52-
53-
54- @pytest .fixture (scope = "session" )
55- def oracle_user () -> str :
56- return "app"
57-
58-
59- @pytest .fixture (scope = "session" )
60- def oracle_password () -> str :
61- return "super-secret"
62-
63-
64- @pytest .fixture (scope = "session" )
65- def oracle_system_password () -> str :
66- return "super-secret"
67-
68-
69- @pytest .fixture (scope = "session" )
70- def oracle18c_service_name () -> str :
71- return "xepdb1"
72-
73-
74- @pytest .fixture (scope = "session" )
75- def oracle23ai_service_name () -> str :
76- return "FREEPDB1"
77-
78-
79- @pytest .fixture (scope = "session" )
80- def oracle_service_name (oracle23ai_service_name : str ) -> str :
81- return oracle23ai_service_name
82-
83-
84- @pytest .fixture (scope = "session" )
85- def oracle18c_port () -> int :
86- return 1514
87-
88-
89- @pytest .fixture (scope = "session" )
90- def oracle23ai_port () -> int :
91- return 1513
92-
93-
94- @pytest .fixture (scope = "session" )
95- def default_oracle_service_name () -> str :
96- return "oracle23ai"
97-
98-
99- @pytest .fixture (scope = "session" )
100- def oracle_port (oracle23ai_port : int ) -> int :
101- return oracle23ai_port
102-
103-
104- @pytest .fixture (scope = "session" )
105- def oracle_docker_compose_files () -> list [Path ]:
106- return [Path (Path (__file__ ).parent / "docker-compose.oracle.yml" )]
107-
108-
109- @pytest .fixture (scope = "session" )
110- def oracle_docker_ip (oracle_docker_services : DockerServiceRegistry ) -> str :
111- return oracle_docker_services .docker_ip
42+ @dataclass
43+ class OracleService (ServiceContainer ):
44+ user : str
45+ password : str
46+ system_password : str
47+ service_name : str
48+
49+
50+ @contextlib .contextmanager
51+ def _provide_oracle_service (docker_service : DockerService , image : str , name : str , service_name : str ):
52+ user = "app"
53+ password = "super-secret"
54+ system_password = "super-secret"
55+
56+ def check (_service : ServiceContainer ) -> bool :
57+ try :
58+ conn = oracledb .connect (
59+ host = _service .host ,
60+ port = _service .port ,
61+ user = user ,
62+ password = password ,
63+ service_name = service_name ,
64+ )
65+ with conn .cursor () as cursor :
66+ cursor .execute ("SELECT 1 FROM dual" )
67+ resp = cursor .fetchone ()
68+ return resp [0 ] == 1 if resp is not None else False
69+ except Exception : # noqa: BLE001
70+ return False
71+
72+ with docker_service .run (
73+ image = image ,
74+ name = name ,
75+ check = check ,
76+ container_port = 1521 ,
77+ env = {
78+ "ORACLE_PASSWORD" : system_password ,
79+ "APP_USER_PASSWORD" : password ,
80+ "APP_USER" : user ,
81+ },
82+ ) as service :
83+ yield OracleService (
84+ host = service .host ,
85+ port = service .port ,
86+ system_password = system_password ,
87+ user = user ,
88+ password = password ,
89+ service_name = service_name ,
90+ )
11291
11392
11493@pytest .fixture (autouse = False , scope = "session" )
115- def oracle23ai_service (
116- oracle_docker_services : DockerServiceRegistry ,
117- oracle_docker_compose_files : list [Path ],
118- oracle23ai_port : int ,
119- oracle23ai_service_name : str ,
120- oracle_system_password : str ,
121- oracle_user : str ,
122- oracle_password : str ,
123- ) -> Generator [None , None , None ]:
124- os .environ ["ORACLE_PASSWORD" ] = oracle_password
125- os .environ ["ORACLE_SYSTEM_PASSWORD" ] = oracle_system_password
126- os .environ ["ORACLE_USER" ] = oracle_user
127- os .environ ["ORACLE23AI_SERVICE_NAME" ] = oracle23ai_service_name
128- os .environ ["ORACLE23AI_PORT" ] = str (oracle23ai_port )
129- oracle_docker_services .start (
130- "oracle23ai" ,
131- docker_compose_files = oracle_docker_compose_files ,
132- timeout = 90 ,
133- pause = 1 ,
134- check = oracle_responsive ,
135- port = oracle23ai_port ,
136- service_name = oracle23ai_service_name ,
137- user = oracle_user ,
138- password = oracle_password ,
139- )
140- yield
94+ def oracle23ai_service (docker_service : DockerService ) -> Generator [OracleService , None , None ]:
95+ with _provide_oracle_service (
96+ image = "gvenzl/oracle-free:23-slim-faststart" ,
97+ name = "oracle23ai" ,
98+ service_name = "FREEPDB1" ,
99+ docker_service = docker_service ,
100+ ) as service :
101+ yield service
141102
142103
143104@pytest .fixture (autouse = False , scope = "session" )
144- def oracle18c_service (
145- oracle_docker_services : DockerServiceRegistry ,
146- oracle_docker_compose_files : list [Path ],
147- oracle18c_port : int ,
148- oracle18c_service_name : str ,
149- oracle_system_password : str ,
150- oracle_user : str ,
151- oracle_password : str ,
152- ) -> Generator [None , None , None ]:
153- os .environ ["ORACLE_PASSWORD" ] = oracle_password
154- os .environ ["ORACLE_SYSTEM_PASSWORD" ] = oracle_system_password
155- os .environ ["ORACLE_USER" ] = oracle_user
156- os .environ ["ORACLE18C_SERVICE_NAME" ] = oracle18c_service_name
157- os .environ ["ORACLE18C_PORT" ] = str (oracle18c_port )
158- oracle_docker_services .start (
159- "oracle18c" ,
160- docker_compose_files = oracle_docker_compose_files ,
161- timeout = 90 ,
162- pause = 1 ,
163- check = oracle_responsive ,
164- port = oracle18c_port ,
165- service_name = oracle18c_service_name ,
166- user = oracle_user ,
167- password = oracle_password ,
168- )
169- yield
105+ def oracle18c_service (docker_service : DockerService ) -> Generator [None , None , None ]:
106+ with _provide_oracle_service (
107+ image = "gvenzl/oracle-free:23-slim-faststart" ,
108+ name = "oracle18c" ,
109+ service_name = "xepdb1" ,
110+ docker_service = docker_service ,
111+ ) as service :
112+ yield service
170113
171114
172115# alias to the latest
173116@pytest .fixture (autouse = False , scope = "session" )
174- def oracle_service (
175- oracle_docker_services : DockerServiceRegistry ,
176- default_oracle_service_name : str ,
177- oracle_docker_compose_files : list [Path ],
178- oracle_port : int ,
179- oracle_service_name : str ,
180- oracle_system_password : str ,
181- oracle_user : str ,
182- oracle_password : str ,
183- ) -> Generator [None , None ]:
184- os .environ ["ORACLE_PASSWORD" ] = oracle_password
185- os .environ ["ORACLE_SYSTEM_PASSWORD" ] = oracle_system_password
186- os .environ ["ORACLE_USER" ] = oracle_user
187- os .environ ["ORACLE_SERVICE_NAME" ] = oracle_service_name
188- os .environ [f"{ default_oracle_service_name .upper ()} _PORT" ] = str (oracle_port )
189- oracle_docker_services .start (
190- name = default_oracle_service_name ,
191- docker_compose_files = oracle_docker_compose_files ,
192- timeout = 90 ,
193- pause = 1 ,
194- check = oracle_responsive ,
195- port = oracle_port ,
196- service_name = oracle_service_name ,
197- user = oracle_user ,
198- password = oracle_password ,
199- )
200- yield
117+ def oracle_service (oracle23ai_service : OracleService ) -> OracleService :
118+ return oracle23ai_service
201119
202120
203121@pytest .fixture (autouse = False , scope = "session" )
204- def oracle_startup_connection (
205- oracle_service : DockerServiceRegistry ,
206- oracle_docker_ip : str ,
207- oracle_port : int ,
208- oracle_service_name : str ,
209- oracle_user : str ,
210- oracle_password : str ,
122+ def oracle18c_startup_connection (
123+ oracle18c_service : OracleService ,
211124) -> Generator [oracledb .Connection , None , None ]:
212125 with oracledb .connect (
213- host = oracle_docker_ip ,
214- port = oracle_port ,
215- user = oracle_user ,
216- service_name = oracle_service_name ,
217- password = oracle_password ,
126+ host = oracle18c_service . host ,
127+ port = oracle18c_service . port ,
128+ user = oracle18c_service . user ,
129+ service_name = oracle18c_service . service_name ,
130+ password = oracle18c_service . password ,
218131 ) as db_connection :
219132 yield db_connection
220133
221134
222135@pytest .fixture (autouse = False , scope = "session" )
223- def oracle18c_startup_connection (
224- oracle18c_service : DockerServiceRegistry ,
225- oracle_docker_ip : str ,
226- oracle18c_port : int ,
227- oracle18c_service_name : str ,
228- oracle_user : str ,
229- oracle_password : str ,
136+ def oracle23ai_startup_connection (
137+ oracle23ai_service : OracleService ,
230138) -> Generator [oracledb .Connection , None , None ]:
231139 with oracledb .connect (
232- host = oracle_docker_ip ,
233- port = oracle18c_port ,
234- user = oracle_user ,
235- service_name = oracle18c_service_name ,
236- password = oracle_password ,
140+ host = oracle23ai_service . host ,
141+ port = oracle23ai_service . port ,
142+ user = oracle23ai_service . user ,
143+ service_name = oracle23ai_service . service_name ,
144+ password = oracle23ai_service . password ,
237145 ) as db_connection :
238146 yield db_connection
239147
240148
241149@pytest .fixture (autouse = False , scope = "session" )
242- def oracle23ai_startup_connection (
243- oracle23ai_service : DockerServiceRegistry ,
244- oracle_docker_ip : str ,
245- oracle23ai_port : int ,
246- oracle23ai_service_name : str ,
247- oracle_user : str ,
248- oracle_password : str ,
249- ) -> Generator [oracledb .Connection , None , None ]:
250- with oracledb .connect (
251- host = oracle_docker_ip ,
252- port = oracle23ai_port ,
253- user = oracle_user ,
254- service_name = oracle23ai_service_name ,
255- password = oracle_password ,
256- ) as db_connection :
257- yield db_connection
150+ def oracle_startup_connection (oracle23ai_startup_connection : oracledb .Connection ) -> oracledb .Connection :
151+ return oracledb .oracle23ai_startup_connection
0 commit comments