66
66
from time import sleep , time # threaded popup
67
67
from typing import Callable , Dict , List , Optional , Tuple , Type , TypedDict , Union # docs
68
68
69
- import jpype # pip install JPype1
70
69
import PySimpleGUI as sg
71
70
72
71
# Wrap optional imports so that pysimplesql can be imported as a single file if desired:
91
90
}
92
91
# fmt: on
93
92
94
- # Load database backends if present
95
- supported_databases = ["SQLite3" , "MySQL" , "PostgreSQL" , "Flatfile" , "Sqlserver" ]
96
- failed_modules = 0
97
- try :
98
- import sqlite3
99
- except ModuleNotFoundError :
100
- failed_modules += 1
101
- try :
102
- import mysql .connector # mysql-connector-python
103
- except ModuleNotFoundError :
104
- failed_modules += 1
105
- try :
106
- import psycopg2
107
- import psycopg2 .extras
108
- except ModuleNotFoundError :
109
- failed_modules += 1
110
- try :
111
- import csv
112
- except ModuleNotFoundError :
113
- failed_modules += 1
114
- try :
115
- import pyodbc
116
- except ModuleNotFoundError :
117
- failed_modules += 1
118
-
119
- if failed_modules == len (supported_databases ):
120
- RuntimeError (
121
- f"You muse have at least one of the following databases installed to use "
122
- f"PySimpleSQL:\n { ', ' .join (supported_databases )} "
123
- )
124
-
125
-
126
93
logger = logging .getLogger (__name__ )
127
94
128
95
# ---------------------------
@@ -5335,6 +5302,11 @@ class LanguagePack:
5335
5302
# Quick Editor
5336
5303
# ------------------------------------------------------------------------------
5337
5304
"quick_edit_title" : "Quick Edit - {data_key}" ,
5305
+ # ------------------------------------------------------------------------------
5306
+ # Error when importing module for driver
5307
+ # ------------------------------------------------------------------------------
5308
+ "import_module_failed_title" : "Problem importing module" ,
5309
+ "import_module_failed" : "Unable to import module neccessary for {name}\n Exception: {exception}\n \n Try `pip install {requires}`" , # fmt: skip # noqa: E501
5338
5310
}
5339
5311
"""
5340
5312
Default LanguagePack.
@@ -6150,6 +6122,7 @@ class SQLDriver:
6150
6122
def __init__ (
6151
6123
self ,
6152
6124
name : str ,
6125
+ requires : List [str ],
6153
6126
placeholder = "%s" ,
6154
6127
table_quote = "" ,
6155
6128
column_quote = "" ,
@@ -6163,6 +6136,7 @@ def __init__(
6163
6136
# Be sure to call super().__init__() in derived class!
6164
6137
self .con = None
6165
6138
self .name = name
6139
+ self .requires = requires
6166
6140
self ._check_reserved_keywords = True
6167
6141
self .win_pb = ProgressBar (
6168
6142
lang .sqldriver_init .format_map (LangFormat (name = name )), 100
@@ -6187,6 +6161,17 @@ def __init__(
6187
6161
# override this in derived __init__() (defaults to single quotes)
6188
6162
self .quote_value_char = value_quote
6189
6163
6164
+ def import_failed (self , exception ) -> None :
6165
+ popup = Popup ()
6166
+ requires = ", " .join (self .requires )
6167
+ popup .ok (
6168
+ lang .import_module_failed_title ,
6169
+ lang .import_module_failed .format_map (
6170
+ LangFormat (name = self .name , requires = requires , exception = exception )
6171
+ ),
6172
+ )
6173
+ exit (0 )
6174
+
6190
6175
def check_reserved_keywords (self , value : bool ) -> None :
6191
6176
"""
6192
6177
SQLDrivers can check to make sure that field names respect their own reserved
@@ -6649,11 +6634,14 @@ def __init__(
6649
6634
):
6650
6635
super ().__init__ (
6651
6636
name = "SQLite" ,
6637
+ requires = ["sqlite3" ],
6652
6638
placeholder = "?" ,
6653
6639
table_quote = '"' ,
6654
6640
column_quote = '"' ,
6655
6641
)
6656
6642
6643
+ self .import_required_modules ()
6644
+
6657
6645
new_database = False
6658
6646
if db_path is not None :
6659
6647
logger .info (f"Opening database: { db_path } " )
@@ -6682,6 +6670,13 @@ def __init__(
6682
6670
self .db_path = db_path
6683
6671
self .win_pb .close ()
6684
6672
6673
+ def import_required_modules (self ):
6674
+ global sqlite3 # noqa PLW0603
6675
+ try :
6676
+ import sqlite3
6677
+ except ModuleNotFoundError as e :
6678
+ self .import_failed (e )
6679
+
6685
6680
def connect (self , database ):
6686
6681
self .con = sqlite3 .connect (database )
6687
6682
@@ -6850,9 +6845,13 @@ def __init__(
6850
6845
# First up the SQLite driver that we derived from
6851
6846
super ().__init__ (":memory:" ) # use an in-memory database
6852
6847
6853
- # Store our Flatfile-specific information
6848
+ # Change Sqlite Sqldriver init set values to Flatfile-specific
6854
6849
self .name = "Flatfile"
6850
+ self .requires = ["csv,sqlite3" ]
6855
6851
self .placeholder = "?" # update
6852
+
6853
+ self .import_required_modules ()
6854
+
6856
6855
self .connect (":memory:" )
6857
6856
self .file_path = file_path
6858
6857
self .delimiter = delimiter
@@ -6917,6 +6916,15 @@ def __init__(
6917
6916
self .commit () # commit them all at the end
6918
6917
self .win_pb .close ()
6919
6918
6919
+ def import_required_modules (self ):
6920
+ global csv # noqa PLW0603
6921
+ global sqlite3 # noqa PLW0603
6922
+ try :
6923
+ import csv
6924
+ import sqlite3
6925
+ except ModuleNotFoundError as e :
6926
+ self .import_failed (e )
6927
+
6920
6928
def save_record (
6921
6929
self , dataset : DataSet , changed_row : dict , where_clause : str = None
6922
6930
) -> ResultSet :
@@ -6969,9 +6977,11 @@ class Mysql(SQLDriver):
6969
6977
def __init__ (
6970
6978
self , host , user , password , database , sql_script = None , sql_commands = None
6971
6979
):
6972
- super ().__init__ (name = "MySQL" )
6980
+ super ().__init__ (name = "MySQL" , requires = [ "mysql-connector-python" ] )
6973
6981
6974
- self .name = "MySQL"
6982
+ self .import_required_modules ()
6983
+
6984
+ self .name = "MySQL" # is this redundant?
6975
6985
self .host = host
6976
6986
self .user = user
6977
6987
self .password = password
@@ -6992,6 +7002,13 @@ def __init__(
6992
7002
6993
7003
self .win_pb .close ()
6994
7004
7005
+ def import_required_modules (self ):
7006
+ global mysql # noqa PLW0603
7007
+ try :
7008
+ import mysql .connector
7009
+ except ModuleNotFoundError as e :
7010
+ self .import_failed (e )
7011
+
6995
7012
def connect (self , retries = 3 ):
6996
7013
attempt = 0
6997
7014
while attempt < retries :
@@ -7168,7 +7185,11 @@ def __init__(
7168
7185
sql_commands = None ,
7169
7186
sync_sequences = False ,
7170
7187
):
7171
- super ().__init__ (name = "Postgres" , table_quote = '"' )
7188
+ super ().__init__ (
7189
+ name = "Postgres" , requires = ["psycopg2" , "psycopg2.extras" ], table_quote = '"'
7190
+ )
7191
+
7192
+ self .import_required_modules ()
7172
7193
7173
7194
self .host = host
7174
7195
self .user = user
@@ -7223,6 +7244,14 @@ def __init__(
7223
7244
self .execute_script (sql_script )
7224
7245
self .win_pb .close ()
7225
7246
7247
+ def import_required_modules (self ):
7248
+ global psycopg2 # noqa PLW0603
7249
+ try :
7250
+ import psycopg2
7251
+ import psycopg2 .extras
7252
+ except ModuleNotFoundError as e :
7253
+ self .import_failed (e )
7254
+
7226
7255
def connect (self , retries = 3 ):
7227
7256
attempt = 0
7228
7257
while attempt < retries :
@@ -7423,9 +7452,13 @@ class Sqlserver(SQLDriver):
7423
7452
def __init__ (
7424
7453
self , host , user , password , database , sql_script = None , sql_commands = None
7425
7454
):
7426
- super ().__init__ (name = "Sqlserver" , table_quote = "[]" , placeholder = "?" )
7455
+ super ().__init__ (
7456
+ name = "Sqlserver" , requires = ["pyodbc" ], table_quote = "[]" , placeholder = "?"
7457
+ )
7427
7458
7428
- self .name = "Sqlserver"
7459
+ self .import_required_modules ()
7460
+
7461
+ self .name = "Sqlserver" # is this redundant?
7429
7462
self .host = host
7430
7463
self .user = user
7431
7464
self .password = password
@@ -7445,6 +7478,13 @@ def __init__(
7445
7478
7446
7479
self .win_pb .close ()
7447
7480
7481
+ def import_required_modules (self ):
7482
+ global pyodbc # noqa PLW0603
7483
+ try :
7484
+ import pyodbc
7485
+ except ModuleNotFoundError as e :
7486
+ self .import_failed (e )
7487
+
7448
7488
def connect (self , retries = 3 , timeout = 3 ):
7449
7489
attempt = 0
7450
7490
while attempt < retries :
@@ -7608,13 +7648,25 @@ class MSAccess(SQLDriver):
7608
7648
"""
7609
7649
7610
7650
def __init__ (self , database_file ):
7611
- super ().__init__ (name = "MSAccess" , table_quote = "[]" , placeholder = "?" )
7651
+ super ().__init__ (
7652
+ name = "MSAccess" , requires = ["Jype1" ], table_quote = "[]" , placeholder = "?"
7653
+ )
7654
+
7655
+ self .import_required_modules ()
7656
+
7612
7657
self .database_file = database_file
7613
7658
self .con = self .connect ()
7614
7659
7615
7660
import os
7616
7661
import sys
7617
7662
7663
+ def import_required_modules (self ):
7664
+ global jpype # noqa PLW0603
7665
+ try :
7666
+ import jpype # pip install JPype1
7667
+ except ModuleNotFoundError as e :
7668
+ self .import_failed (e )
7669
+
7618
7670
def connect (self ):
7619
7671
# Get the path to the 'lib' folder
7620
7672
current_path = os .path .dirname (os .path .abspath (__file__ ))
0 commit comments