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
# ---------------------------
@@ -5325,6 +5292,11 @@ class LanguagePack:
5325
5292
# Quick Editor
5326
5293
# ------------------------------------------------------------------------------
5327
5294
"quick_edit_title" : "Quick Edit - {data_key}" ,
5295
+ # ------------------------------------------------------------------------------
5296
+ # Error when importing module for driver
5297
+ # ------------------------------------------------------------------------------
5298
+ "import_module_failed_title" : "Problem importing module" ,
5299
+ "import_module_failed" : "Unable to import module neccessary for {name}\n Exception: {exception}\n \n Try `pip install {requires}`" , # fmt: skip # noqa: E501
5328
5300
}
5329
5301
"""
5330
5302
Default LanguagePack.
@@ -6140,6 +6112,7 @@ class SQLDriver:
6140
6112
def __init__ (
6141
6113
self ,
6142
6114
name : str ,
6115
+ requires : List [str ],
6143
6116
placeholder = "%s" ,
6144
6117
table_quote = "" ,
6145
6118
column_quote = "" ,
@@ -6153,6 +6126,7 @@ def __init__(
6153
6126
# Be sure to call super().__init__() in derived class!
6154
6127
self .con = None
6155
6128
self .name = name
6129
+ self .requires = requires
6156
6130
self ._check_reserved_keywords = True
6157
6131
self .win_pb = ProgressBar (
6158
6132
lang .sqldriver_init .format_map (LangFormat (name = name )), 100
@@ -6177,6 +6151,17 @@ def __init__(
6177
6151
# override this in derived __init__() (defaults to single quotes)
6178
6152
self .quote_value_char = value_quote
6179
6153
6154
+ def import_failed (self , exception ) -> None :
6155
+ popup = Popup ()
6156
+ requires = ", " .join (self .requires )
6157
+ popup .ok (
6158
+ lang .import_module_failed_title ,
6159
+ lang .import_module_failed .format_map (
6160
+ LangFormat (name = self .name , requires = requires , exception = exception )
6161
+ ),
6162
+ )
6163
+ exit (0 )
6164
+
6180
6165
def check_reserved_keywords (self , value : bool ) -> None :
6181
6166
"""
6182
6167
SQLDrivers can check to make sure that field names respect their own reserved
@@ -6639,11 +6624,14 @@ def __init__(
6639
6624
):
6640
6625
super ().__init__ (
6641
6626
name = "SQLite" ,
6627
+ requires = ["sqlite3" ],
6642
6628
placeholder = "?" ,
6643
6629
table_quote = '"' ,
6644
6630
column_quote = '"' ,
6645
6631
)
6646
6632
6633
+ self .import_required_modules ()
6634
+
6647
6635
new_database = False
6648
6636
if db_path is not None :
6649
6637
logger .info (f"Opening database: { db_path } " )
@@ -6672,6 +6660,13 @@ def __init__(
6672
6660
self .db_path = db_path
6673
6661
self .win_pb .close ()
6674
6662
6663
+ def import_required_modules (self ):
6664
+ global sqlite3 # noqa PLW0603
6665
+ try :
6666
+ import sqlite3
6667
+ except ModuleNotFoundError as e :
6668
+ self .import_failed (e )
6669
+
6675
6670
def connect (self , database ):
6676
6671
self .con = sqlite3 .connect (database )
6677
6672
@@ -6840,9 +6835,13 @@ def __init__(
6840
6835
# First up the SQLite driver that we derived from
6841
6836
super ().__init__ (":memory:" ) # use an in-memory database
6842
6837
6843
- # Store our Flatfile-specific information
6838
+ # Change Sqlite Sqldriver init set values to Flatfile-specific
6844
6839
self .name = "Flatfile"
6840
+ self .requires = ["csv,sqlite3" ]
6845
6841
self .placeholder = "?" # update
6842
+
6843
+ self .import_required_modules ()
6844
+
6846
6845
self .connect (":memory:" )
6847
6846
self .file_path = file_path
6848
6847
self .delimiter = delimiter
@@ -6907,6 +6906,15 @@ def __init__(
6907
6906
self .commit () # commit them all at the end
6908
6907
self .win_pb .close ()
6909
6908
6909
+ def import_required_modules (self ):
6910
+ global csv # noqa PLW0603
6911
+ global sqlite3 # noqa PLW0603
6912
+ try :
6913
+ import csv
6914
+ import sqlite3
6915
+ except ModuleNotFoundError as e :
6916
+ self .import_failed (e )
6917
+
6910
6918
def save_record (
6911
6919
self , dataset : DataSet , changed_row : dict , where_clause : str = None
6912
6920
) -> ResultSet :
@@ -6959,9 +6967,11 @@ class Mysql(SQLDriver):
6959
6967
def __init__ (
6960
6968
self , host , user , password , database , sql_script = None , sql_commands = None
6961
6969
):
6962
- super ().__init__ (name = "MySQL" )
6970
+ super ().__init__ (name = "MySQL" , requires = [ "mysql-connector-python" ] )
6963
6971
6964
- self .name = "MySQL"
6972
+ self .import_required_modules ()
6973
+
6974
+ self .name = "MySQL" # is this redundant?
6965
6975
self .host = host
6966
6976
self .user = user
6967
6977
self .password = password
@@ -6982,6 +6992,13 @@ def __init__(
6982
6992
6983
6993
self .win_pb .close ()
6984
6994
6995
+ def import_required_modules (self ):
6996
+ global mysql # noqa PLW0603
6997
+ try :
6998
+ import mysql .connector
6999
+ except ModuleNotFoundError as e :
7000
+ self .import_failed (e )
7001
+
6985
7002
def connect (self , retries = 3 ):
6986
7003
attempt = 0
6987
7004
while attempt < retries :
@@ -7158,7 +7175,11 @@ def __init__(
7158
7175
sql_commands = None ,
7159
7176
sync_sequences = False ,
7160
7177
):
7161
- super ().__init__ (name = "Postgres" , table_quote = '"' )
7178
+ super ().__init__ (
7179
+ name = "Postgres" , requires = ["psycopg2" , "psycopg2.extras" ], table_quote = '"'
7180
+ )
7181
+
7182
+ self .import_required_modules ()
7162
7183
7163
7184
self .host = host
7164
7185
self .user = user
@@ -7213,6 +7234,14 @@ def __init__(
7213
7234
self .execute_script (sql_script )
7214
7235
self .win_pb .close ()
7215
7236
7237
+ def import_required_modules (self ):
7238
+ global psycopg2 # noqa PLW0603
7239
+ try :
7240
+ import psycopg2
7241
+ import psycopg2 .extras
7242
+ except ModuleNotFoundError as e :
7243
+ self .import_failed (e )
7244
+
7216
7245
def connect (self , retries = 3 ):
7217
7246
attempt = 0
7218
7247
while attempt < retries :
@@ -7413,9 +7442,13 @@ class Sqlserver(SQLDriver):
7413
7442
def __init__ (
7414
7443
self , host , user , password , database , sql_script = None , sql_commands = None
7415
7444
):
7416
- super ().__init__ (name = "Sqlserver" , table_quote = '"' , placeholder = "?" )
7445
+ super ().__init__ (
7446
+ name = "Sqlserver" , requires = ["pyodbc" ], table_quote = '"' , placeholder = "?"
7447
+ )
7417
7448
7418
- self .name = "Sqlserver"
7449
+ self .import_required_modules ()
7450
+
7451
+ self .name = "Sqlserver" # is this redundant?
7419
7452
self .host = host
7420
7453
self .user = user
7421
7454
self .password = password
@@ -7435,6 +7468,13 @@ def __init__(
7435
7468
7436
7469
self .win_pb .close ()
7437
7470
7471
+ def import_required_modules (self ):
7472
+ global pyodbc # noqa PLW0603
7473
+ try :
7474
+ import pyodbc
7475
+ except ModuleNotFoundError as e :
7476
+ self .import_failed (e )
7477
+
7438
7478
def connect (self , retries = 3 , timeout = 3 ):
7439
7479
attempt = 0
7440
7480
while attempt < retries :
@@ -7598,13 +7638,25 @@ class MSAccess(SQLDriver):
7598
7638
"""
7599
7639
7600
7640
def __init__ (self , database_file ):
7601
- super ().__init__ (name = "MSAccess" , table_quote = "[]" , placeholder = "?" )
7641
+ super ().__init__ (
7642
+ name = "MSAccess" , requires = ["Jype1" ], table_quote = "[]" , placeholder = "?"
7643
+ )
7644
+
7645
+ self .import_required_modules ()
7646
+
7602
7647
self .database_file = database_file
7603
7648
self .con = self .connect ()
7604
7649
7605
7650
import os
7606
7651
import sys
7607
7652
7653
+ def import_required_modules (self ):
7654
+ global jpype # noqa PLW0603
7655
+ try :
7656
+ import jpype # pip install JPype1
7657
+ except ModuleNotFoundError as e :
7658
+ self .import_failed (e )
7659
+
7608
7660
def connect (self ):
7609
7661
# Get the path to the 'lib' folder
7610
7662
current_path = os .path .dirname (os .path .abspath (__file__ ))
0 commit comments