Skip to content

Commit 7a97927

Browse files
committed
refs #278 Unit Test example for ProgressAnimate
Not perfect yet, but shows the basic concepts of testing for both no failures and expected failures. I tried to fix things in ProgressAnimate as I went along so that hopefully you can see the correlation between what was being tested, and the fixes that went in to pass the tests. If you haven't used pytest before, there's a few things to do: - pip install pytest - make sure pysimplesql is reachable as a module. The easiest way is to do a local installation by running `pip -e .` in the pysimplesql root directory - from the commandline, run `pytest` to run all tests. Or you can run tests for a specific file, I.e. `pytest progressanimate_test.py`
2 parents 65239d9 + 2d6938f commit 7a97927

File tree

2 files changed

+95
-40
lines changed

2 files changed

+95
-40
lines changed

examples/MSAccess_examples/install_java.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,17 @@
66
run. This also serves as an example to automatically download a local Java installation
77
for your own projects.
88
"""
9-
import jdk
109
import os
1110
import pysimplesql as ss
1211
import PySimpleGUI as sg
1312
import subprocess
1413

14+
try:
15+
import jdk
16+
except ModuleNotFoundError:
17+
sg.popup_error("You must `pip install install-jdk` to use this example")
18+
exit(0)
19+
1520

1621
# -------------------------------------------------
1722
# ROUTINES TO INSTALL JAVA IF USER DOES NOT HAVE IT

pysimplesql/pysimplesql.py

Lines changed: 89 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@
6666
from time import sleep, time # threaded popup
6767
from typing import Callable, Dict, List, Optional, Tuple, Type, TypedDict, Union # docs
6868

69-
import jpype # pip install JPype1
7069
import PySimpleGUI as sg
7170

7271
# Wrap optional imports so that pysimplesql can be imported as a single file if desired:
@@ -91,38 +90,6 @@
9190
}
9291
# fmt: on
9392

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-
12693
logger = logging.getLogger(__name__)
12794

12895
# ---------------------------
@@ -5335,6 +5302,11 @@ class LanguagePack:
53355302
# Quick Editor
53365303
# ------------------------------------------------------------------------------
53375304
"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}\nException: {exception}\n\nTry `pip install {requires}`", # fmt: skip # noqa: E501
53385310
}
53395311
"""
53405312
Default LanguagePack.
@@ -6150,6 +6122,7 @@ class SQLDriver:
61506122
def __init__(
61516123
self,
61526124
name: str,
6125+
requires: List[str],
61536126
placeholder="%s",
61546127
table_quote="",
61556128
column_quote="",
@@ -6163,6 +6136,7 @@ def __init__(
61636136
# Be sure to call super().__init__() in derived class!
61646137
self.con = None
61656138
self.name = name
6139+
self.requires = requires
61666140
self._check_reserved_keywords = True
61676141
self.win_pb = ProgressBar(
61686142
lang.sqldriver_init.format_map(LangFormat(name=name)), 100
@@ -6187,6 +6161,17 @@ def __init__(
61876161
# override this in derived __init__() (defaults to single quotes)
61886162
self.quote_value_char = value_quote
61896163

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+
61906175
def check_reserved_keywords(self, value: bool) -> None:
61916176
"""
61926177
SQLDrivers can check to make sure that field names respect their own reserved
@@ -6649,11 +6634,14 @@ def __init__(
66496634
):
66506635
super().__init__(
66516636
name="SQLite",
6637+
requires=["sqlite3"],
66526638
placeholder="?",
66536639
table_quote='"',
66546640
column_quote='"',
66556641
)
66566642

6643+
self.import_required_modules()
6644+
66576645
new_database = False
66586646
if db_path is not None:
66596647
logger.info(f"Opening database: {db_path}")
@@ -6682,6 +6670,13 @@ def __init__(
66826670
self.db_path = db_path
66836671
self.win_pb.close()
66846672

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+
66856680
def connect(self, database):
66866681
self.con = sqlite3.connect(database)
66876682

@@ -6850,9 +6845,13 @@ def __init__(
68506845
# First up the SQLite driver that we derived from
68516846
super().__init__(":memory:") # use an in-memory database
68526847

6853-
# Store our Flatfile-specific information
6848+
# Change Sqlite Sqldriver init set values to Flatfile-specific
68546849
self.name = "Flatfile"
6850+
self.requires = ["csv,sqlite3"]
68556851
self.placeholder = "?" # update
6852+
6853+
self.import_required_modules()
6854+
68566855
self.connect(":memory:")
68576856
self.file_path = file_path
68586857
self.delimiter = delimiter
@@ -6917,6 +6916,15 @@ def __init__(
69176916
self.commit() # commit them all at the end
69186917
self.win_pb.close()
69196918

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+
69206928
def save_record(
69216929
self, dataset: DataSet, changed_row: dict, where_clause: str = None
69226930
) -> ResultSet:
@@ -6969,9 +6977,11 @@ class Mysql(SQLDriver):
69696977
def __init__(
69706978
self, host, user, password, database, sql_script=None, sql_commands=None
69716979
):
6972-
super().__init__(name="MySQL")
6980+
super().__init__(name="MySQL", requires=["mysql-connector-python"])
6981+
6982+
self.import_required_modules()
69736983

6974-
self.name = "MySQL"
6984+
self.name = "MySQL" # is this redundant?
69756985
self.host = host
69766986
self.user = user
69776987
self.password = password
@@ -6992,6 +7002,13 @@ def __init__(
69927002

69937003
self.win_pb.close()
69947004

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+
69957012
def connect(self, retries=3):
69967013
attempt = 0
69977014
while attempt < retries:
@@ -7168,7 +7185,11 @@ def __init__(
71687185
sql_commands=None,
71697186
sync_sequences=False,
71707187
):
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()
71727193

71737194
self.host = host
71747195
self.user = user
@@ -7223,6 +7244,14 @@ def __init__(
72237244
self.execute_script(sql_script)
72247245
self.win_pb.close()
72257246

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+
72267255
def connect(self, retries=3):
72277256
attempt = 0
72287257
while attempt < retries:
@@ -7425,7 +7454,9 @@ def __init__(
74257454
):
74267455
super().__init__(name="Sqlserver", table_quote="[]", placeholder="?")
74277456

7428-
self.name = "Sqlserver"
7457+
self.import_required_modules()
7458+
7459+
self.name = "Sqlserver" # is this redundant?
74297460
self.host = host
74307461
self.user = user
74317462
self.password = password
@@ -7445,6 +7476,13 @@ def __init__(
74457476

74467477
self.win_pb.close()
74477478

7479+
def import_required_modules(self):
7480+
global pyodbc # noqa PLW0603
7481+
try:
7482+
import pyodbc
7483+
except ModuleNotFoundError as e:
7484+
self.import_failed(e)
7485+
74487486
def connect(self, retries=3, timeout=3):
74497487
attempt = 0
74507488
while attempt < retries:
@@ -7608,13 +7646,25 @@ class MSAccess(SQLDriver):
76087646
"""
76097647

76107648
def __init__(self, database_file):
7611-
super().__init__(name="MSAccess", table_quote="[]", placeholder="?")
7649+
super().__init__(
7650+
name="MSAccess", requires=["Jype1"], table_quote="[]", placeholder="?"
7651+
)
7652+
7653+
self.import_required_modules()
7654+
76127655
self.database_file = database_file
76137656
self.con = self.connect()
76147657

76157658
import os
76167659
import sys
76177660

7661+
def import_required_modules(self):
7662+
global jpype # noqa PLW0603
7663+
try:
7664+
import jpype # pip install JPype1
7665+
except ModuleNotFoundError as e:
7666+
self.import_failed(e)
7667+
76187668
def connect(self):
76197669
# Get the path to the 'lib' folder
76207670
current_path = os.path.dirname(os.path.abspath(__file__))

0 commit comments

Comments
 (0)