From e46ea59f2c883f02ccef87974f106bf07cf4a3d0 Mon Sep 17 00:00:00 2001 From: Jose Navas Date: Tue, 7 Apr 2015 11:38:08 -0700 Subject: [PATCH 1/2] Moving setitem to the base class --- .../base_metadata_template.py | 79 +++++++++++++++++-- qiita_db/metadata_template/sample_template.py | 74 ----------------- .../test/test_prep_template.py | 8 +- 3 files changed, 76 insertions(+), 85 deletions(-) diff --git a/qiita_db/metadata_template/base_metadata_template.py b/qiita_db/metadata_template/base_metadata_template.py index 24079cddd..59b46bcb9 100644 --- a/qiita_db/metadata_template/base_metadata_template.py +++ b/qiita_db/metadata_template/base_metadata_template.py @@ -44,7 +44,8 @@ from qiita_core.exceptions import IncompetentQiitaDeveloperError from qiita_db.exceptions import (QiitaDBUnknownIDError, - QiitaDBNotImplementedError) + QiitaDBNotImplementedError, + QiitaDBColumnError) from qiita_db.base import QiitaObject from qiita_db.sql_connection import SQLConnectionHandler from qiita_db.util import (exists_table, get_table_cols, @@ -308,17 +309,79 @@ def handler(x): " in template %d" % (key, self._id, self._md_template.id)) - def __setitem__(self, key, value): - r"""Sets the metadata value for the category `key` + def __setitem__(self, column, value): + r"""Sets the metadata value for the category `column` Parameters ---------- - key : str - The metadata category - value : obj - The new value for the category + column : str + The column to update + value : str + The value to set. This is expected to be a str on the assumption + that psycopg2 will cast as necessary when updating. + + Raises + ------ + QiitaDBColumnError + If the column does not exist in the table """ - raise QiitaDBNotImplementedError() + conn_handler = SQLConnectionHandler() + + # try dynamic tables + sql = """SELECT EXISTS ( + SELECT column_name + FROM information_schema.columns + WHERE table_name=%s + AND table_schema='qiita' + AND column_name=%s)""" + exists_dynamic = conn_handler.execute_fetchone( + sql, (self._dynamic_table, column))[0] + # try required_sample_info + sql = """SELECT EXISTS ( + SELECT column_name + FROM information_schema.columns + WHERE table_name=%s + AND table_schema='qiita' + AND column_name=%s)""" + exists_required = conn_handler.execute_fetchone( + sql, (self._table, column))[0] + + if exists_dynamic: + # catching error so we can check if the error is due to different + # column type or something else + try: + sql = """UPDATE qiita.{0} + SET {1}=%s + WHERE sample_id=%s""".format(self._dynamic_table, + column) + conn_handler.execute(sql, (value, self._id)) + except Exception as e: + column_type = conn_handler.execute_fetchone( + """SELECT data_type + FROM information_schema.columns + WHERE column_name=%s AND table_schema='qiita' + """, (column,))[0] + value_type = type(value).__name__ + + if column_type != value_type: + raise ValueError( + 'The new value being added to column: "{0}" is "{1}" ' + '(type: "{2}"). However, this column in the DB is of ' + 'type "{3}". Please change the value in your updated ' + 'template or reprocess your sample template.'.format( + column, value, value_type, column_type)) + else: + raise e + elif exists_required: + # here is not required the type check as the required fields have + # an explicit type check + sql = """UPDATE qiita.{0} + SET {1}=%s + WHERE sample_id=%s""".format(self._table, column) + conn_handler.execute(sql, (value, self._id)) + else: + raise QiitaDBColumnError("Column %s does not exist in %s" % + (column, self._dynamic_table)) def __delitem__(self, key): r"""Removes the sample with sample id `key` from the database diff --git a/qiita_db/metadata_template/sample_template.py b/qiita_db/metadata_template/sample_template.py index 7616db846..2b649c4d3 100644 --- a/qiita_db/metadata_template/sample_template.py +++ b/qiita_db/metadata_template/sample_template.py @@ -63,80 +63,6 @@ def _check_template_class(self, md_template): if not isinstance(md_template, SampleTemplate): raise IncompetentQiitaDeveloperError() - def __setitem__(self, column, value): - r"""Sets the metadata value for the category `column` - - Parameters - ---------- - column : str - The column to update - value : str - The value to set. This is expected to be a str on the assumption - that psycopg2 will cast as necessary when updating. - - Raises - ------ - QiitaDBColumnError - If the column does not exist in the table - """ - conn_handler = SQLConnectionHandler() - - # try dynamic tables - exists_dynamic = conn_handler.execute_fetchone(""" - SELECT EXISTS ( - SELECT column_name - FROM information_schema.columns - WHERE table_name='{0}' - AND table_schema='qiita' - AND column_name='{1}')""".format(self._dynamic_table, - column))[0] - # try required_sample_info - exists_required = conn_handler.execute_fetchone(""" - SELECT EXISTS ( - SELECT column_name - FROM information_schema.columns - WHERE table_name='required_sample_info' - AND table_schema='qiita' - AND column_name='{0}')""".format(column))[0] - - if exists_dynamic: - # catching error so we can check if the error is due to different - # column type or something else - try: - conn_handler.execute(""" - UPDATE qiita.{0} - SET {1}=%s - WHERE sample_id=%s""".format(self._dynamic_table, - column), (value, self._id)) - except Exception as e: - column_type = conn_handler.execute_fetchone(""" - SELECT data_type - FROM information_schema.columns - WHERE column_name=%s AND table_schema='qiita' - """, (column,))[0] - value_type = type(value).__name__ - - if column_type != value_type: - raise ValueError( - 'The new value being added to column: "{0}" is "{1}" ' - '(type: "{2}"). However, this column in the DB is of ' - 'type "{3}". Please change the value in your updated ' - 'template or reprocess your sample template.'.format( - column, value, value_type, column_type)) - else: - raise e - elif exists_required: - # here is not required the type check as the required fields have - # an explicit type check - conn_handler.execute(""" - UPDATE qiita.required_sample_info - SET {0}=%s - WHERE sample_id=%s - """.format(column), (value, self._id)) - else: - raise QiitaDBColumnError("Column %s does not exist in %s" % - (column, self._dynamic_table)) - class SampleTemplate(MetadataTemplate): r"""Represent the SampleTemplate of a study. Provides access to the diff --git a/qiita_db/metadata_template/test/test_prep_template.py b/qiita_db/metadata_template/test/test_prep_template.py index 5a43347fe..d903eb7d3 100644 --- a/qiita_db/metadata_template/test/test_prep_template.py +++ b/qiita_db/metadata_template/test/test_prep_template.py @@ -220,9 +220,11 @@ def test_get_none(self): class TestPrepSampleReadWrite(BaseTestPrepSample): """Tests the PrepSample class""" def test_setitem(self): - """setitem raises an error (currently not allowed)""" - with self.assertRaises(QiitaDBNotImplementedError): - self.tester['barcodesequence'] = 'GTCCGCAAGTTA' + with self.assertRaises(QiitaDBColumnError): + self.tester['column that does not exist'] = 0.3 + self.assertEqual(self.tester['center_name'], 'ANL') + self.tester['center_name'] = "FOO" + self.assertEqual(self.tester['center_name'], "FOO") def test_delitem(self): """delitem raises an error (currently not allowed)""" From 8474ca435eb0f6dc4c189b3bdacf3c3a34e718ba Mon Sep 17 00:00:00 2001 From: Jose Navas Date: Tue, 7 Apr 2015 14:38:38 -0700 Subject: [PATCH 2/2] addressing @squirrelo's comments --- .../base_metadata_template.py | 46 ++++++++++--------- .../test/test_prep_template.py | 4 ++ .../test/test_sample_template.py | 4 ++ 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/qiita_db/metadata_template/base_metadata_template.py b/qiita_db/metadata_template/base_metadata_template.py index 59b46bcb9..6b6333ef6 100644 --- a/qiita_db/metadata_template/base_metadata_template.py +++ b/qiita_db/metadata_template/base_metadata_template.py @@ -324,6 +324,8 @@ def __setitem__(self, column, value): ------ QiitaDBColumnError If the column does not exist in the table + ValueError + If the value type does not match the one in the DB """ conn_handler = SQLConnectionHandler() @@ -347,42 +349,42 @@ def __setitem__(self, column, value): sql, (self._table, column))[0] if exists_dynamic: - # catching error so we can check if the error is due to different - # column type or something else - try: sql = """UPDATE qiita.{0} SET {1}=%s WHERE sample_id=%s""".format(self._dynamic_table, column) - conn_handler.execute(sql, (value, self._id)) - except Exception as e: - column_type = conn_handler.execute_fetchone( - """SELECT data_type - FROM information_schema.columns - WHERE column_name=%s AND table_schema='qiita' - """, (column,))[0] - value_type = type(value).__name__ - - if column_type != value_type: - raise ValueError( - 'The new value being added to column: "{0}" is "{1}" ' - '(type: "{2}"). However, this column in the DB is of ' - 'type "{3}". Please change the value in your updated ' - 'template or reprocess your sample template.'.format( - column, value, value_type, column_type)) - else: - raise e elif exists_required: # here is not required the type check as the required fields have # an explicit type check sql = """UPDATE qiita.{0} SET {1}=%s WHERE sample_id=%s""".format(self._table, column) - conn_handler.execute(sql, (value, self._id)) else: raise QiitaDBColumnError("Column %s does not exist in %s" % (column, self._dynamic_table)) + try: + conn_handler.execute(sql, (value, self._id)) + except Exception as e: + # catching error so we can check if the error is due to different + # column type or something else + column_type = conn_handler.execute_fetchone( + """SELECT data_type + FROM information_schema.columns + WHERE column_name=%s AND table_schema='qiita' + """, (column,))[0] + value_type = type(value).__name__ + + if column_type != value_type: + raise ValueError( + 'The new value being added to column: "{0}" is "{1}" ' + '(type: "{2}"). However, this column in the DB is of ' + 'type "{3}". Please change the value in your updated ' + 'template or reprocess your sample template.'.format( + column, value, value_type, column_type)) + else: + raise e + def __delitem__(self, key): r"""Removes the sample with sample id `key` from the database diff --git a/qiita_db/metadata_template/test/test_prep_template.py b/qiita_db/metadata_template/test/test_prep_template.py index d903eb7d3..b916abd20 100644 --- a/qiita_db/metadata_template/test/test_prep_template.py +++ b/qiita_db/metadata_template/test/test_prep_template.py @@ -222,6 +222,10 @@ class TestPrepSampleReadWrite(BaseTestPrepSample): def test_setitem(self): with self.assertRaises(QiitaDBColumnError): self.tester['column that does not exist'] = 0.3 + + with self.assertRaises(ValueError): + self.tester['emp_status_id'] = "Error!" + self.assertEqual(self.tester['center_name'], 'ANL') self.tester['center_name'] = "FOO" self.assertEqual(self.tester['center_name'], "FOO") diff --git a/qiita_db/metadata_template/test/test_sample_template.py b/qiita_db/metadata_template/test/test_sample_template.py index 0639cdb64..3b6a6fca4 100644 --- a/qiita_db/metadata_template/test/test_sample_template.py +++ b/qiita_db/metadata_template/test/test_sample_template.py @@ -208,6 +208,10 @@ class TestSampleReadWrite(BaseTestSample): def test_setitem(self): with self.assertRaises(QiitaDBColumnError): self.tester['column that does not exist'] = 0.30 + + with self.assertRaises(ValueError): + self.tester['collection_timestamp'] = "Error!" + self.assertEqual(self.tester['tot_nitro'], 1.41) self.tester['tot_nitro'] = '1234.5' self.assertEqual(self.tester['tot_nitro'], 1234.5)