Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
7aae917
DButils: changed to 2.0 metadata binding syntax
Jan 10, 2024
38f12f2
DButils: changed to declarative mapping
Jan 10, 2024
6099814
dbp_testing.py: add bind to table drop
Jan 11, 2024
9903e22
DButils.getTraceback: get the sqlalchemy 2.0 join syntax right
Jan 17, 2024
8eb5697
DButils.py: fixed join methods
Jan 24, 2024
028dbf5
moved the bind from Metadata constructor to table creation
Jan 24, 2024
9c54844
DButils.py: fixed assertion error
Jan 25, 2024
4becd0d
DButils.py: fixed all warning messages
Jan 30, 2024
812baa8
undid change so CI will run 2.0
Feb 2, 2024
7a12790
added bind to drop_all and removed self from dbu.engine
Feb 6, 2024
83c4964
casted string with sqlalchemy.sql.text()
Feb 22, 2024
fbe6787
added my name to contributors
Feb 22, 2024
2e1cb80
added bind to create_all
May 20, 2024
bde52aa
removed bind from metadata
May 20, 2024
aca843c
scrubber: fix raw SQL syntax in version_number_check
May 20, 2024
8002ce0
clean_test_db: fix raw SQL syntax in vacuum
May 20, 2024
34a04ab
removed extra parentheses
May 21, 2024
edc8b6a
sqlalchemy.sql was used without it imported
Sep 18, 2024
80c5eab
move the bind from Metadata constructor to table creation (to reflect…
Jan 9, 2025
ac70274
execute no longer taking direct SQL string
Jan 17, 2025
e05685a
adding self to bind argument
Jan 20, 2025
ba5c4bf
Creates error directory if it doesn't exist
Feb 7, 2025
403d1c7
Updating python print syntax to a function call
Feb 7, 2025
587b029
Updated imp to importlib for load_source past Python 3.4
Feb 10, 2025
f92c10c
Updated error message checking to comply with Python 3.12 syntax
Mar 11, 2025
c862aed
Updating concatanation
Apr 1, 2025
62ed2ee
Creating function to handle the update of imp to importlib
Apr 1, 2025
d60fac1
Test for load_source function
Apr 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
pip install --user python-dateutil
sudo apt update
sudo apt install python3-pip
pip3 install --user "sqlalchemy<2.0"
pip3 install --user sqlalchemy
pip3 install --user python-dateutil
- persist_to_workspace:
root: ~/.local
Expand Down
136 changes: 77 additions & 59 deletions dbprocessing/DButils.py

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions dbprocessing/Utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -560,3 +560,18 @@ def readconfig(config_filepath):
else:
ans[section][item] = (ans[section][item], 0, 0)
return ans
def load_source(modname, filepath, module):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PEP8 specifies space (i.e. one empty line) between the functions.

Can you document parameters/returns as in the other functions?

The module argument doesn't appear to be used--can it be removed? (And then update calls to it, of course).

"""
The imp module was removed in Python 3.4, thus, adaptations were made so the imp.load_source feature can be used for later Python versions
"""
try:
import importlib.util
import importlib.machinery
loader = importlib.machinery.SourceFileLoader(modname, filepath)
spec = importlib.util.spec_from_file_location(modname, filepath, loader=loader)
module = importlib.util.module_from_spec(spec)
loader.exec_module(module)
except ImportError:
import imp # Depracated in Python 3.4
module = imp.load_source(modname, filepath)
return module
5 changes: 3 additions & 2 deletions dbprocessing/dbprocessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from __future__ import print_function

import datetime
import imp
import os
import shutil
import sys
Expand Down Expand Up @@ -259,7 +258,9 @@ def figureProduct(self, filename=None):
claimed = []
for code, desc, arg, product in act_insp:
try:
inspect = imp.load_source('inspect', code)
fname = code
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this assignment necessary? Can't we just pass "code" directly to load_source?

inspect = None
inspect = Utils.load_source('inspect',fname, inspect)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

space after the comma per PEP-8

except IOError as msg:
DBlogging.dblogger.error('Inspector: "{0}" not found: {1}'.format(code, msg))
if os.path.isfile(code + ' '):
Expand Down
1 change: 1 addition & 0 deletions dbprocessing/runMe.py
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,7 @@ def moveToError(self, fname):
DBlogging.dblogger.debug("Entered moveToError: {0}".format(fname))

path = self.dbu.getErrorPath()
os.makedirs(path, exist_ok=True) # Creates error directory if doesn't exist
if os.path.isfile(os.path.join(path, os.path.basename(fname) ) ):
#TODO do I really want to remove old version:?
os.remove( os.path.join(path, os.path.basename(fname) ) )
Expand Down
8 changes: 2 additions & 6 deletions developer/scripts/clean_test_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

import datetime
import dbprocessing.DButils

import sqlalchemy

def find_related_products(dbu, prod_ids, outputs=False):
"""Find all input/output products for a list of products
Expand Down Expand Up @@ -67,7 +67,6 @@ def find_related_products(dbu, prod_ids, outputs=False):
for prod_id in range(1, 190):
if prod_id in keep_products:
continue

files = [rec.file_id for rec in dbu.getFiles(product=prod_id)]
for file_id in files:
dbu._purgeFileFromDB(file_id, trust_id=True, commit=False)
Expand All @@ -76,13 +75,11 @@ def find_related_products(dbu, prod_ids, outputs=False):
.filter_by(product_id=prod_id)
for ll in list(sq):
dbu.session.delete(ll)

sq = dbu.session.query(dbu.Productprocesslink)\
.filter_by(input_product_id=prod_id)
results = list(sq)
for ll in results:
dbu.session.delete(ll)

sq = dbu.session.query(dbu.Process).filter_by(output_product=prod_id)
results = list(sq)
for ll in results:
Expand All @@ -99,7 +96,6 @@ def find_related_products(dbu, prod_ids, outputs=False):
results = list(sq)
for ll in results:
dbu.session.delete(ll)

dbu.delProduct(prod_id) # performs commit

# Only keep a few dates
Expand All @@ -116,5 +112,5 @@ def find_related_products(dbu, prod_ids, outputs=False):
for file_id in delme:
dbu._purgeFileFromDB(file_id, trust_id=True, commit=False)
dbu.commitDB()
dbu.session.execute('VACUUM')
dbu.session.execute(sqlalchemy.sql.text("VACUUM"))
dbu.commitDB()
1 change: 1 addition & 0 deletions docs/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Current developers (*italics denote project administrators*) are:
| Andrew Walker
| Meilin Yan
| Xiaoguang Yang
| Elisabeth Drakatos

Acknowledgements
================
Expand Down
9 changes: 3 additions & 6 deletions examples/scripts/CreateDBsabrs.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ def init_db(self, user, password, db, host='localhost', port=5432):
url = "postgresql://{0}:{1}@{2}:{3}/{4}"
url = url.format(user, password, host, port, db)
self.engine = create_engine(url, echo=False, encoding='utf-8')
self.metadata = sqlalchemy.MetaData(bind=self.engine)
self.metadata.reflect()
self.metadata = sqlalchemy.MetaData()
self.metadata.reflect(bind=self.engine)

def createDB(self):
"""
Expand Down Expand Up @@ -318,10 +318,7 @@ def createDB(self):
# engine = create_engine('postgres:///' + self.filename, echo=False)
# metadata.bind = engine

metadata.create_all(checkfirst=True)
# self.engine = engine
# self.metadata = metadata

metadata.create_all(checkfirst=True, bind=self.engine)
def addMission(self, filename):
"""utility to add a mission"""
self.dbu = DButils.DButils(filename)
Expand Down
4 changes: 2 additions & 2 deletions functional_test/scripts/run_rot13_L0toL1.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ def doProcess(infiles, outfile):
infiles = sorted(args[:-1])
outfile = args[-1]

print "infiles", infiles
print "outfile", outfile
print("infiles ", infiles)
print("outfile ", outfile)
doProcess(infiles, outfile)
8 changes: 4 additions & 4 deletions functional_test/scripts/run_rot13_L1toL2.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#!/usr/bin/env python
import codecs
from optparse import OptionParser

def doProcess(infile, outfile):
with open(outfile, 'w') as output:
with open(infile) as infile:
output.write(infile.read().encode('rot13'))

output.write(codecs.encode(infile.read(), 'rot_13'))
Comment on lines -7 to +8
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

go ahead and retain the empty line at the end of the function

if __name__ == '__main__':
usage = "usage: %prog infile outfile"
parser = OptionParser(usage=usage)
Expand All @@ -18,6 +18,6 @@ def doProcess(infile, outfile):
infile = args[0]
outfile = args[-1]

print "infile", infile
print "outfile", outfile
print("infile ", infile)
print("outfile ", outfile)
doProcess(infile, outfile)
2 changes: 1 addition & 1 deletion functional_test/scripts/run_rot13_RUN_timebase.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ def doProcess(infile):

infile = args[0]

print "infile", infile
print("infile ", infile)
doProcess(infile)
4 changes: 3 additions & 1 deletion scripts/scrubber.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import argparse

import sqlalchemy.sql

from dbprocessing import DButils

class scrubber(object):
Expand All @@ -24,7 +26,7 @@ def parents_are_newest(self):
print(np.difference(n))

def version_number_check(self):
x = self.dbu.session.execute("SELECT max(interface_version), max(quality_version), max(revision_version) FROM file").fetchone()
x = self.dbu.session.execute(sqlalchemy.sql.text("SELECT max(interface_version), max(quality_version), max(revision_version) FROM file")).fetchone()
if x[0] >= 1000:
print("A interface version is too large")
if x[1] >= 1000:
Expand Down
6 changes: 3 additions & 3 deletions unit_tests/dbp_testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ def removeTestDB(self):
"""
if self.pg:
self.dbu.session.close()
self.dbu.metadata.drop_all()
self.dbu.metadata.drop_all(bind=self.dbu.engine)
self.dbu.closeDB() # Before the database is removed...
del self.dbu
shutil.rmtree(self.td)
Expand Down Expand Up @@ -282,7 +282,7 @@ def loadData(self, filename):
# persist_selectable added 1.3 (mapped_table deprecated)
tbl = insp.persist_selectable\
if hasattr(insp, 'persist_selectable') else insp.mapped_table
tbl.drop()
tbl.drop(bind=self.dbu.engine)
self.dbu.metadata.remove(tbl)
del self.dbu.Unixtime
if data['productprocesslink']\
Expand All @@ -306,7 +306,7 @@ def loadData(self, filename):
sel = "SELECT pg_catalog.setval(pg_get_serial_sequence("\
"'{table}', '{column}'), {maxid})".format(
table=t, column=idcolumn, maxid=maxid)
self.dbu.session.execute(sel)
self.dbu.session.execute(sqlalchemy.sql.text(sel))
self.dbu.commitDB()
# Re-reference directories since new data loaded
self.dbu.MissionDirectory = self.dbu.getMissionDirectory()
Expand Down
2 changes: 1 addition & 1 deletion unit_tests/test_CreateDB.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def test1(self):
dbu = DButils.DButils(testdb)
if pg:
dbu.session.close()
dbu.metadata.drop_all()
dbu.metadata.drop_all(bind=dbu.engine)
del dbu
finally:
shutil.rmtree(td)
Expand Down
6 changes: 2 additions & 4 deletions unit_tests/test_DBRunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,8 @@ def test_parse_dbrunner_args_bad(self):
finally:
sys.stderr.close()
sys.stderr = oldstderr
self.assertEqual(
'{}: error: {}'.format(os.path.basename(sys.argv[0]), msg), err)


running_script = os.path.basename(sys.argv[0])
self.assertTrue(err.startswith("{}: error: argument".format(running_script)))
Comment on lines -89 to +90
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per PEP 8, keep two blank lines after the class definition

class DBRunnerCalcRunmeTests(unittest.TestCase, dbp_testing.AddtoDBMixin):
"""DBRunner tests of calc_runme"""

Expand Down
2 changes: 1 addition & 1 deletion unit_tests/test_DButils.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def tearDown(self):
super(DBUtilsEmptyTests, self).tearDown()
if self.pg:
self.dbu.session.close()
self.dbu.metadata.drop_all()
self.dbu.metadata.drop_all(bind=self.dbu.engine)
self.dbu.closeDB()
del self.dbu
shutil.rmtree(self.td)
Expand Down
23 changes: 13 additions & 10 deletions unit_tests/test_Inspector.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import datetime
import unittest
import tempfile
import imp
import sys
import warnings
import os

Expand All @@ -14,6 +14,7 @@
from dbprocessing import Version
from dbprocessing import DButils
from dbprocessing import Diskfile
from dbprocessing import Utils

class InspectorFunctions(unittest.TestCase):
"""Tests of the inspector functions"""
Expand Down Expand Up @@ -59,9 +60,9 @@ def setUp(self):
self.makeTestDB()
self.loadData(os.path.join(dbp_testing.testsdir, 'data', 'db_dumps',
'testDB_dump.json'))
self.inspect = imp.load_source('inspect', os.path.join(
dbp_testing.testsdir, 'inspector', 'rot13_L1.py'))

filename = os.path.join(dbp_testing.testsdir, 'inspector', 'rot13_L1.py')
self.inspect = None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you update load_source not to take the module argument, all these None assignments can go away (several in this file)

self.inspect = Utils.load_source('inspect', filename, self.inspect)
def tearDown(self):
super(InspectorClass, self).tearDown()
self.removeTestDB()
Expand All @@ -80,10 +81,11 @@ def test_inspector(self):
self.assertEqual(repr(Diskfile.Diskfile(goodfile, self.dbu)), repr(self.inspect.Inspector(goodfile, self.dbu, 1,)()))
#self.assertEqual(None, self.inspect.Inspector(goodfile, self.dbu, 1,).extract_YYYYMMDD())
# This inspector sets the data_level - not allowed
inspect = imp.load_source('inspect', os.path.join(
dbp_testing.testsdir, 'inspector', 'rot13_L1_dlevel.py'))
with warnings.catch_warnings(record=True) as w:
self.assertEqual(repr(Diskfile.Diskfile(goodfile, self.dbu)), repr(self.inspect.Inspector(goodfile, self.dbu, 1,)()))
filename = os.path.join(dbp_testing.testsdir, 'inspector', 'rot13_L1_dlevel.py')
inspect = None
inspect = Utils.load_source('inspect', filename, inspect)
with warnings.catch_warnings(record=True) as w:
self.assertEqual(repr(Diskfile.Diskfile(goodfile, self.dbu)), repr(inspect.Inspector(goodfile, self.dbu, 1,)()))
self.assertEqual(len(w), 1)
self.assertTrue(isinstance(w[0].message, UserWarning))
self.assertEqual('Inspector rot13_L1_dlevel.py: set level to 2.0, '
Expand All @@ -93,8 +95,9 @@ def test_inspector(self):
# The file doesn't match the inspector pattern...
badfile = os.path.join(
dbp_testing.testsdir, 'inspector', 'testDB_01_first.raw')
inspect = imp.load_source('inspect', os.path.join(
dbp_testing.testsdir, 'inspector', 'rot13_L1.py'))
filename = os.path.join(dbp_testing.testsdir, 'inspector', 'rot13_L1.py')
inspect = None
inspect = Utils.load_source('inspect', filename, inspect)
self.assertEqual(None, inspect.Inspector(badfile, self.dbu, 1,)())

def test_inspector_regex(self):
Expand Down
11 changes: 9 additions & 2 deletions unit_tests/test_Utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,14 @@ def test_toDatetime(self):
self.assertEqual(
datetime.datetime(2010, 1, 1, 23, 59, 59, 999999),
Utils.toDatetime(datetime.date(2010, 1, 1), end=True))


def test_load_source(self):
"""Testing load_source in Utils.py"""
filename = "temp_testfile.py"
with open(filename, "w") as f:
f.write("def hello():\n return 'Hello, world!'\n")
inspect = None
module = Utils.load_source("temp_testfile", filename, inspect)
self.assertEqual(module.hello(), 'Hello, world!')

Comment on lines +307 to +315
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice test. Do leave a blank line before it, and two after (because it's the end of the class). Use tempfile to make a temporary directory and put your test file in there, then clean it up after (with a try/finally)--that way you're not leaving it in the current directory.

if __name__ == "__main__":
unittest.main()
4 changes: 2 additions & 2 deletions unit_tests/test_tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def setUp(self):
self.engine = sqlalchemy.create_engine(
'sqlite:///{}'.format(os.path.join(self.td, 'test.sqlite')),
echo=False)
self.metadata = sqlalchemy.schema.MetaData(bind=self.engine)
self.metadata = sqlalchemy.schema.MetaData()

def tearDown(self):
"""Delete test database"""
Expand All @@ -54,7 +54,7 @@ def makeTables(self, *tables):
name: sqlalchemy.schema.Table(
name, self.metadata, *dbprocessing.tables.definition(name))
for name in tables}
self.metadata.create_all()
self.metadata.create_all(bind=self.engine)
actual = sqlalchemy.inspection.inspect(self.engine)\
.get_table_names()
self.assertEqual(sorted(tables), sorted(actual))
Expand Down