def __init__(self, logFile, uid, pwd, tsvFileName, screenNamePos): ''' Make connection to MySQL wrapper. @param logFile: file where log entries will be appended. @type logFile: String @param uid: MySQL user under which to log in. Assumed to be other than None @type uid: String @param pwd: MySQL password for user uid. May be None. @type pwd: {String | None} @param tsvFileName: name of TSV file where rows of edxprod's certificates_generatedcertificate table are located. It is assumed that the caller verified existence and readability of this file. @type String @param screenNamePos: Zero-origin position of the screen name column in the TSV file from certificates_generatedcertificate @type screenNamePos: int ''' self.uid = uid self.pwd = pwd self.tsvFileName = tsvFileName self.screenNamePos = screenNamePos self.logFile = logFile if pwd is None: self.mysqldb = MySQLDB(user=uid, db='EdxPrivate') else: self.mysqldb = MySQLDB(user=uid, passwd=pwd, db='EdxPrivate')
def testWithMySQLPassword(self): try: # Set a password for the unittest user: if self.mysql_ge_5_7: self.mysqldb.execute("SET PASSWORD FOR unittest@localhost = 'foobar'") else: self.mysqldb.execute("SET PASSWORD FOR unittest@localhost = PASSWORD('foobar')") self.mysqldb.close() # We should be unable to log in without a pwd: with self.assertRaises(ValueError): self.mysqldb = MySQLDB(host='localhost', user='******', db='unittest') # Open new pymysql_db.MySQLDb instance, supplying pwd: self.mysqldb = MySQLDB(host='localhost', user='******', passwd='foobar', db='unittest') # Do a test query: self.buildSmallDb() res = self.mysqldb.query("SELECT col2 FROM unittest WHERE col1 = 10;").next() self.assertEqual(res, 'col1') # Bulk insert is also different for pwd vs. none: self.testBulkInsert() finally: # Make sure the remove the pwd from user unittest, # so that other tests will run successfully: if self.mysql_ge_5_7: self.mysqldb.execute("SET PASSWORD FOR unittest@localhost = ''") else: self.mysqldb.execute("SET PASSWORD FOR unittest@localhost = PASSWORD('')")
def log_into_mysql(self, user, db_pwd, db=None, host='localhost', **kwargs): try: # Try logging in, specifying the database in which all the tables # will be created: db = MySQLDB(user=user, passwd=db_pwd, db=db, host=host, **kwargs) except ValueError as e: # Does the db not exist yet? if str(e).find("OperationalError(1049,") > -1: # Log in, specifying an always present db to 'use': db = MySQLDB(user=user, passwd=db_pwd, db='information_schema', host=host) # Create the db: db.execute('CREATE DATABASE %s;' % self.config_info.canvas_db_aux) else: raise DatabaseError(f"Cannot open Canvas database:\n{repr(e)}") except Exception as e: raise DatabaseError(f"Cannot open Canvas database:\n{repr(e)}") # Work in UTC, b/c default on Mac MySQL 8 is local time, # on Centos MySQL 5.7 is UTC; it's a mess: (err, _warn) = db.execute('SET @@session.time_zone = "+00:00"') if err is not None: self.log_warn(f"Cannot set session time zone to UTC: {repr(err)}") return db
def setUp(self): self.allColNames = TestAddAnonToActivityGrade.studentmoduleExcerptColNames[ 0] for colName in TestAddAnonToActivityGrade.studentmoduleExcerptColNames[ 1:]: self.allColNames += ',' + colName self.db = MySQLDB(user='******', passwd='', db='unittest') self.db.dropTable('StudentmoduleExcerpt') self.db.createTable( 'StudentmoduleExcerpt', TestAddAnonToActivityGrade.studentmoduleExcerptSchema, temporary=False) #***temporary=True) self.db.bulkInsert( 'StudentmoduleExcerpt', TestAddAnonToActivityGrade.studentmoduleExcerptColNames, TestAddAnonToActivityGrade.studentmoduleExcerptValues) self.db.createTable( 'ActivityGrade', TestAddAnonToActivityGrade.studentmoduleExcerptSchema) # Make sure there isn't left over content (if the table existed): self.db.truncateTable('ActivityGrade') # Rudimentary UserGrade table: self.db.dropTable('UserGrade') self.db.createTable('UserGrade', TestAddAnonToActivityGrade.userGradeExcerptSchema, temporary=False) self.db.bulkInsert('UserGrade', TestAddAnonToActivityGrade.userGradeExcerptColNames, TestAddAnonToActivityGrade.userGradeExcerptValues) self.db.close()
def tearDown(self): self.db = MySQLDB(user='******', passwd='', db='unittest') # Can't drop tables: hangs #self.db.dropTable('StudentmoduleExcerpt') #self.db.dropTable('ActivityGrade') self.db.close() pass
def setUpClass(cls): super(AuxTableCopyTester, cls).setUpClass() # Read config file to see which MySQL server test_host we should # run the tests on. If setup.py does not exist, copy # setupSample.py to setup.py: config_info = ConfigInfo() cls.utils = Utilities() test_host = config_info.test_default_host user = config_info.test_default_user cls.test_host = test_host cls.user = user mysql_pwd = cls.mysql_pwd = cls.utils.get_db_pwd(test_host, unittests=True) cls.mysql_pwd = mysql_pwd db = AuxTableCopyTester.db = MySQLDB(user=user, passwd=mysql_pwd, db='information_schema', host=test_host) # If not working on localhost, where we expect a db # 'Unittest" Ensure there is a unittest db for us to work in. # We'll delete it later: if test_host == 'localhost': cls.db_name = 'Unittest' cls.mysql_pwd = '' else: cls.db_name = UnittestDbFinder(db).db_name db.close()
def testQueryIterator(self): self.buildSmallDb() for rowNum, result in enumerate(self.mysqldb.query('SELECT col1,col2 FROM unittest')): if rowNum == 0: self.assertEqual((10, 'col1'), result) elif rowNum == 1: self.assertEqual((20, 'col2'), result) elif rowNum == 2: self.assertEqual((30, 'col3'), result) # Test the dict cursor self.mysqldb.close() self.mysqldb = MySQLDB(host='localhost', user='******', db='unittest', cursor_class=Cursors.DICT) for result in self.mysqldb.query('SELECT col1,col2 FROM unittest'): self.assertIsInstance(result, dict) if result['col1'] == 10: self.assertEqual(result['col2'], 'col1') elif result['col1'] == 20: self.assertEqual(result['col2'], 'col2') elif result['col1'] == 30: self.assertEqual(result['col2'], 'col3')
def __init__(self, extIdsFileName): user = '******' # Try to find pwd in specified user's $HOME/.ssh/mysql currUserHomeDir = os.getenv('HOME') if currUserHomeDir is None: pwd = None else: try: # Need to access MySQL db as its 'root': with open(os.path.join(currUserHomeDir, '.ssh/mysql_root')) as fd: pwd = fd.readline().strip() # Switch user to 'root' b/c from now on it will need to be root: user = '******' except IOError: # No .ssh subdir of user's home, or no mysql inside .ssh: pwd = None self.db = MySQLDB(user=user, passwd=pwd, db='Misc') self.makeTmpExtsTable() self.loadExtIds(extIdsFileName) outfile = tempfile.NamedTemporaryFile(prefix='extsIntsScreenNames', suffix='.csv', delete=True) # Need to close this file, and thereby delete it, # so that MySQL is willing to write to it. Yes, # that's a race condition. But this is an # admin script, run by one person: outfile.close() self.findScreenNames(outfile.name) self.computeAnonFromScreenNames(outfile.name)
def ensureOpenMySQLDb(self): try: with open('/home/%s/.ssh/mysql' % self.currUser, 'r') as fd: self.mySQLPwd = fd.readline().strip() self.mysqlDb = MySQLDB(user=self.currUser, passwd=self.mySQLPwd, db=self.mainThread.defaultDb) except Exception: try: # Try w/o a pwd: self.mySQLPwd = None self.mysqlDb = MySQLDB(user=self.currUser, db=self.defaultDb) except Exception as e: # Remember the error msg for later: self.dbError = ` e ` self.mysqlDb = None return self.mysqlDb
def __init__(self, bsonFileName, mysqlDbObj=None, forumTableName='contents', allUsersTableName='EdxPrivate.UserGrade', anonymize=True, allowAnonScreenName=False): ''' Given a .bson file containing OpenEdX Forum entries, anonymize the entries (if desired), and place them into a MySQL table. :param bsonFileName: full path the .bson table. Set to None if instantiating for unit testing. :type bsonFileName: String :param mysqlDbObj: a pymysql_utils.MySQLDB object where anonymized entries are to be placed. If None, a new such object is created into MySQL db 'EdxForum' :type mysqlDbObj: MySQLDB :param forumTableName: name of table into which anonymized Forum entries are to be placed :type forumTableName: String :param allUsersTable: fully qualified name of table listing all in-the-clear mySQLUser names of users who post to the Forum. Used to redact their names from their own posts. :type allUsersTable: String :param anonymize: If true, Forum post entries in the MySQL table will be anonymized :type anonymize: bool :param allow_anon_screen_name: if True, then occurrences of poster's name in post bodies are replaced by <redacName_<anon_screen_name>>, where anon_screen_name is the hash used in other tables of the OpenEdX data. :type allow_anon_screen_name: Bool ''' self.bsonFileName = bsonFileName self.forumTableName = forumTableName self.forumDbName = 'EdxForum' self.allUsersTableName = allUsersTableName self.anonymize = anonymize self.allowAnonScreenName = allowAnonScreenName # If not unittest, but regular run, then mysqlDbObj is None if mysqlDbObj is None: self.mysql_passwd = self.getMySQLPasswd() self.mysql_dbhost ='localhost' self.mysql_user = getpass.getuser() # mySQLUser that started this process self.mydb = MySQLDB(mySQLUser=self.mysql_user, passwd=self.mysql_passwd, db=self.forumDbName) else: self.mydb = mysqlDbObj self.counter=0 self.userCache = {} self.userSet = set() warnings.filterwarnings('ignore', category=MySQLdb.Warning) self.setupLogging() self.prepDatabase()
def log_into_mysql(cls, user, db_pwd, db=None): host = AuxTableCopyTester.test_host try: # Try logging in, specifying the database in which all the tables # will be created: db = MySQLDB(user=user, passwd=db_pwd, db=db, host=host) except ValueError as e: # Does unittest not exist yet? if str(e).find("OperationalError(1049,") > -1: # Log in without specifying a db to 'use': db = MySQLDB(user=user, passwd=db_pwd, host=host) # Create the db: db.execute('CREATE DATABASE %s;' % 'unittest') else: raise RuntimeError("Cannot open Canvas database: %s" % repr(e)) except Exception as e: raise RuntimeError("Cannot open Canvas database: %s" % repr(e)) return db
def __init__(self, uid, pwd, db='Edx'): ''' ****** Update this comment header Make connection to MySQL wrapper. @param uid: MySQL user under which to log in. Assumed to be other than None @type uid: String @param pwd: MySQL password for user uid. May be None. @type pwd: {String | None} ''' self.db = db if pwd is None: self.mysqldbStudModule = MySQLDB(user=uid, db=db) else: self.mysqldbStudModule = MySQLDB(user=uid, passwd=pwd, db=db) # Create a string with the parameters of the SELECT call, # (activity_grade_id,student_id,...): self.colSpec = AnonAndModIDAdder.ACTIVITY_GRADE_COL_NAMES[0] for colName in AnonAndModIDAdder.ACTIVITY_GRADE_COL_NAMES[1:]: self.colSpec += ',' + colName self.pullRowByRow()
def __init__(self, user, pwd): self.ipCountryXlater = IpCountryDict() self.user = user self.pwd = pwd self.db = MySQLDB(user=self.user, passwd=self.pwd, db='Edx') self.db.dropTable(UserCountryTableCreator.DEST_TABLE) self.db.createTable( UserCountryTableCreator.DEST_TABLE, OrderedDict({ 'anon_screen_name': 'varchar(40) NOT NULL DEFAULT ""', 'two_letter_country': 'varchar(2) NOT NULL DEFAULT ""', 'three_letter_country': 'varchar(3) NOT NULL DEFAULT ""', 'country': 'varchar(255) NOT NULL DEFAULT ""' }))
def setUp(self): if not TestPymysqlUtils.env_ok: raise RuntimeError(TestPymysqlUtils.err_msg) try: self.mysqldb = MySQLDB(host='localhost', port=3306, user='******', db='unittest') except ValueError as e: self.fail(str(e) + " (For unit testing, localhost MySQL server must have user 'unittest' without password, and a database called 'unittest')") # Make MySQL version more convenient to check: if (TestPymysqlUtils.major == 5 and TestPymysqlUtils.minor >= 7) or \ TestPymysqlUtils.major >= 8: self.mysql_ge_5_7 = True else: self.mysql_ge_5_7 = False
def __init__(self, user, pwd): self.ipCountryXlater = IpCountryDict() self.user = user self.pwd = pwd self.db = MySQLDB(user=self.user, passwd=self.pwd, db='Edx') # Make sure table exists. It should, and it should be filled # with all anon_screen_name and countries up the previous # load: self.db.createTable( UserCountryTableCreator.DEST_TABLE, OrderedDict({ 'anon_screen_name': 'varchar(40) NOT NULL DEFAULT ""', 'two_letter_country': 'varchar(2) NOT NULL DEFAULT ""', 'three_letter_country': 'varchar(3) NOT NULL DEFAULT ""', 'country': 'varchar(255) NOT NULL DEFAULT ""' }))
def setUpClass(cls): super(FindUnittestDbTester, cls).setUpClass() # Get whether to test on localhost, or on # remote host: config_info = ConfigInfo() cls.test_host = config_info.test_default_host cls.user = config_info.test_default_user utils = Utilities() cls.db = MySQLDB(user=cls.user, passwd=utils.get_db_pwd(cls.test_host, unittests=True), db='information_schema', host=cls.test_host)
def __init__(self, majors_table='sankey'): ''' ''' self.majors_table = majors_table self.mysql_passwd = self.getMySQLPasswd() self.mysql_dbhost = 'localhost' self.mysql_user = getpass.getuser( ) # mySQLUser that started this process self.mydb = MySQLDB(user=self.mysql_user, passwd=self.mysql_passwd, db=self.majors_table) (nodes, links) = self.get_nodes_and_links() SankeyDiagram.plot_sankey(nodes, links, plot_title="Majors Transitions")
def __init__(self, user, pwd): self.ipCountryXlater = IpCountryDict() self.user = user self.pwd = pwd self.db = MySQLDB(user=self.user, passwd=self.pwd, db='Edx') # Make sure table exists. It should, and it should be filled # with all anon_screen_name and countries up the previous # load: createCmd = '''CREATE TABLE UserCountry ( anon_screen_name varchar(40) NOT NULL DEFAULT "", two_letter_country varchar(2) NOT NULL DEFAULT "", three_letter_country varchar(3) NOT NULL DEFAULT "", country varchar(255) NOT NULL DEFAULT "" ) ENGINE=MyISAM; ''' self.db.dropTable('UserCountry') print("Creating table UserCountry...") self.db.execute(createCmd) print("Done creating table UserCountry.")
def __init__(self, user, db, table, totalRows=None): ''' Constructor ''' home = os.environ['HOME'] with open(os.path.join(home, '.ssh/mysql')) as pwdFd: pwd = pwdFd.read().strip() db = MySQLDB(db=db, user=user, passwd=pwd) # Number of rows pulled from EventIp: rowCount = 0 # First row to get in the select statement: nextBatchStartRow = -UniqueAnonIpExtractor.BATCH_SIZE with open('/tmp/anonIps.csv', 'w') as fd: #*****with sys.stdout as fd: fd.write('anon_screen_name,ip\n') numRecords = db.query('SELECT count(*) from EventIp').next() if numRecords == 0: sys.exit() if totalRows is None: totalRows = numRecords while rowCount < numRecords and rowCount < totalRows: nextBatchStartRow += UniqueAnonIpExtractor.BATCH_SIZE for (anon_screen_name, ip) in db.query('SELECT anon_screen_name, event_ip from EventIp LIMIT %s,%s' % \ (nextBatchStartRow, UniqueAnonIpExtractor.BATCH_SIZE)): if UniqueAnonIpExtractor.seenAnons.get( anon_screen_name, None) is None: # The anon_screen_name in the db could actually be NULL, a.k.a. None. # Ignore those: if anon_screen_name is not None: fd.write(anon_screen_name + ',' + ip + '\n') UniqueAnonIpExtractor.seenAnons[ anon_screen_name] = 1 rowCount += 1 if (rowCount % UniqueAnonIpExtractor.BATCH_SIZE) == 0: print("Did %s rows." % rowCount) if rowCount >= totalRows: break print('Finished %s rows; %s unique anon_screen_names' % (rowCount, len(UniqueAnonIpExtractor.seenAnons.keys())))
def testCreateTempTable(self): mySchema = { 'col1' : 'INT', 'col2' : 'varchar(255)', 'col3' : 'FLOAT', 'col4' : 'TEXT', #'col5' : 'JSON' # Only works MySQL 5.7 and up. } self.mysqldb.createTable('myTbl', mySchema, temporary=True) # Check that tbl exists. # NOTE: can't use query to mysql.informationschema, # b/c temp tables aren't listed there. try: # Will return some tuple; we don't # care what exaclty, as long as the # cmd doesn't fail: self.mysqldb.query('DESC myTbl').next() except Exception: self.fail('Temporary table not found after creation.') # Start new session, which should remove the table. # Query mysql information schema to check for table # present. Use raw cursor to test independently from # the pymysql_utils query() method: self.mysqldb.close() try: self.mysqldb = MySQLDB(host='localhost', port=3306, user='******', db='unittest') except ValueError as e: self.fail(str(e) + "Could not re-establish MySQL connection.") # NOTE: can't use query to mysql.informationschema, # b/c temp tables aren't listed there. try: self.mysqldb.query('DESC myTbl').next() self.fail("Temporary table did not disappear with session exit.") except ValueError: pass
def tearDownClass(cls): super(AuxTableCopyTester, cls).tearDownClass() if cls.test_host == 'localhost': return db = None try: # Remove the unittest db we created: print(f"Removing database '{cls.db_name}'...") db = MySQLDB(user=cls.user, passwd=cls.mysql_pwd, db='information_schema', host=cls.test_host) db.execute(f"DROP DATABASE {cls.db_name}") print(print(f"Done removing database '{cls.db_name}'...")) #AuxTableCopyTester.copier_obj.close() pass finally: if db is not None: db.close()
def setUp(self): self.mongoDb = MongoDB(dbName="unittest", collection="tinyForum") # Fill the little MongoDB with test JSON lines self.resetMongoTestDb() self.mysqldb = MySQLDB(mySQLUser='******', db='unittest') # Start with an empty result MySQL table for each test: self.mysqldb.dropTable('contents') # Fill the fake UserGrade table with records of course participants: self.resetMySQLUserListDb() # Instantiate a Forum scrubber without the # name of a bson file that contains forum # records. That 'None' for the bson file will # make the class understand that it's being # instantiated for a unit test. self.forumScrubberAnonymized = EdxForumScrubber(None, mysqlDbObj=self.mysqldb, forumTableName='contents', allUsersTableName='unittest.UserGrade') self.forumScrubberRelatable = EdxForumScrubber(None, mysqlDbObj=self.mysqldb, forumTableName='contents', allUsersTableName='unittest.UserGrade', allowAnonScreenName=True) self.forumScrubberClear = EdxForumScrubber(None, mysqlDbObj=self.mysqldb, forumTableName='contents', allUsersTableName='unittest.UserGrade', anonymize=False)
def setUpClass(cls): super(CanvasUtilsTests, cls).setUpClass() # Read config file to see which MySQL server test_host we should # run the tests on. If setup.py does not exist, copy # setupSample.py to setup.py: config_info = ConfigInfo() test_host = config_info.test_default_host user = config_info.test_default_user cls.canvas_pwd_file = config_info.canvas_pwd_file # Access to common functionality: cls.utils = Utilities() # If not working on localhost, where we expect a db # 'Unittest" Ensure there is a unittest db for us to work in. # We'll delete it later: if test_host == 'localhost': db_name = 'Unittest' else: db = None db = MySQLDB(host=test_host, user=config_info.test_default_user, passwd=cls.utils.get_db_pwd(test_host, unittests=True)) try: db_name = UnittestDbFinder(db).db_name except Exception as e: raise AssertionError( f"Cannot open db to find a unittest db: {repr(e)}") finally: if db is not None: db.close() CanvasUtilsTests.test_host = test_host CanvasUtilsTests.unittests_db_nm = db_name CanvasUtilsTests.user = user
def testAddAnonToActivityTable(self): try: # Modify the fake courseware_studentmodule excerpt # to add anon_screen_name, computer plusses/minusses, # compute grade percentage, etc: AnonAndModIDAdder('unittest', '', db='unittest', testing=True) self.db = MySQLDB(user='******', passwd='', db='unittest') for rowNum, row in enumerate( self.db.query('SELECT %s FROM ActivityGrade;' % self.allColNames)): #print(row) if rowNum == 0: self.assertEqual(( 0, 1, 'myCourse', '3', 10.0, 30.0, '', '', -1, datetime.datetime(2014, 1, 10, 4, 10, 45), datetime.datetime(2014, 2, 10, 10, 14, 40), 'modtype1', 'abc', 'Guided Walkthrough', 'i4x://Carnegie/2013/chapter/1fee4bc0d5384cb4aa7a0d65f3ac5d9b' ), row) elif rowNum == 1: self.assertEqual(( 1, 2, 'myCourse', '5', 10.0, 50.0, '', '', -1, datetime.datetime(2014, 1, 10, 11, 30, 23), datetime.datetime(2014, 2, 10, 14, 30, 12), 'modtype2', 'def', 'Evaluation', 'i4x://Carnegie/2013/chapter/5d08d2bae3ac4047bf5abe1d8dd16ac3' ), row) elif rowNum == 2: self.assertEqual(( 2, 3, 'yourCourse', '8', 10.0, 80.0, '', '', -1, datetime.datetime(2014, 1, 10, 18, 34, 12), datetime.datetime(2014, 2, 10, 19, 10, 33), 'modtype2', 'None', 'Introduction', 'i4x://Carnegie/2013/chapter/9a9455cd30bd4c14819542bcd11bfcf8' ), row) finally: self.db.close()
def __init__(self, user, pwd): self.ipCountryXlater = IpCountryDict() self.user = user self.pwd = pwd self.db = MySQLDB(user=self.user, passwd=self.pwd, db='Edx') # Make sure table exists. It should, and it should be filled # with all anon_screen_name and countries up the previous # load: createCmd = '''CREATE TABLE %s ( anon_screen_name varchar(40) NOT NULL DEFAULT "", two_letter_country varchar(2) NOT NULL DEFAULT "", three_letter_country varchar(3) NOT NULL DEFAULT "", country varchar(255) NOT NULL DEFAULT "", region varchar(255) NOT NULL DEFAULT "", city varchar(255) NOT NULL DEFAULT "", lat_long point NOT NULL ) ENGINE=MyISAM; ''' % UserDetailedLocationTableCreator.DEST_TABLE self.db.dropTable('UserCountry') print("Creating table %..." % UserDetailedLocationTableCreator.DEST_TABLE) self.db.execute(createCmd) print("Done creating table %s." % UserDetailedLocationTableCreator.DEST_TABLE)
def testBadParameters(self): self.mysqldb.close() # Test setting parameters illegally to None: try: with self.assertRaises(Exception) as context: MySQLDB(host=None, port=3306, user='******', db='unittest') self.assertTrue("None value(s) for ['host']; none of host,port,user,passwd or db must be None" in str(context.exception)) with self.assertRaises(Exception) as context: MySQLDB(host='localhost', port=None, user='******', db='unittest') self.assertTrue("None value(s) for ['port']; none of host,port,user,passwd or db must be None" in str(context.exception)) with self.assertRaises(Exception) as context: MySQLDB(host='localhost', port=3306, user=None, db='unittest') self.assertTrue("None value(s) for ['user']; none of host,port,user,passwd or db must be None" in str(context.exception)) with self.assertRaises(Exception) as context: MySQLDB(host='localhost', port=3306, user='******', db=None) self.assertTrue("None value(s) for ['db']; none of host,port,user,passwd or db must be None" in str(context.exception)) with self.assertRaises(Exception) as context: MySQLDB(host='localhost', port=3306, user='******', passwd=None, db='unittest') self.assertTrue("None value(s) for ['passwd']; none of host,port,user,passwd or db must be None" in str(context.exception)) with self.assertRaises(Exception) as context: MySQLDB(host=None, port=3306, user=None, db=None) self.assertTrue("None value(s) for ['host', 'db', 'user']; none of host,port,user,passwd or db must be None" in str(context.exception)) except AssertionError: # Create a better message than 'False is not True'. # That useless msg is generated if an expected exception # above is NOT raised: raise AssertionError('Expected ValueError exception "%s" was not raised.' % context.exception.message) # Check data types of parameters: try: # One illegal type: host==10: with self.assertRaises(Exception) as context: # Integer instead of string for host: MySQLDB(host=10, port=3306, user='******', db='myDb') self.assertTrue("Value(s) ['host'] have bad type;host,user,passwd, and db must be strings; port must be int." in str(context.exception)) # Two illegal types: host and user: with self.assertRaises(Exception) as context: # Integer instead of string for host: MySQLDB(host=10, port=3306, user=30, db='myDb') self.assertTrue("Value(s) ['host', 'user'] have bad type;host,user,passwd, and db must be strings; port must be int." in str(context.exception)) # Port being string instead of required int: with self.assertRaises(Exception) as context: # Integer instead of string for host: MySQLDB(host='myHost', port='3306', user='******', db='myDb') self.assertTrue("Port must be an integer; was" in str(context.exception)) except AssertionError: # Create a better message than 'False is not True'. # That useless msg is generated if an expected exception # above is NOT raised: raise AssertionError('Expected ValueError exception "%s" was not raised.' % context.exception.message)
def setUpClass(cls): # Ensure that a user unittest with the proper # permissions exists in the db: TestPymysqlUtils.env_ok = True TestPymysqlUtils.err_msg = '' try: needed_grants = ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'CREATE', 'CREATE TEMPORARY TABLES', 'DROP', 'ALTER'] mysqldb = MySQLDB(host='localhost', port=3306, user='******', db='unittest') grant_query = 'SHOW GRANTS FOR unittest@localhost' query_it = mysqldb.query(grant_query) # First row of the SHOW GRANTS response should be # one of: first_grants = ["GRANT USAGE ON *.* TO 'unittest'@'localhost'", "GRANT USAGE ON *.* TO `unittest`@`localhost`" ] # Second row depends on the order in which the # grants were provided. The row will look something # like: # GRANT SELECT, INSERT, UPDATE, DELETE, ..., CREATE, DROP, ALTER ON `unittest`.* TO 'unittest'@'localhost' # Verify: usage_grant = query_it.next() if usage_grant not in first_grants: TestPymysqlUtils.err_msg = ''' User 'unittest' is missing USAGE grant needed to run the tests. Also need this in your MySQL: %s ''' % 'GRANT %s ON unittest.* TO unittest@localhost' % ','.join(needed_grants) TestPymysqlUtils.env_ok = False return grants_str = query_it.next() for needed_grant in needed_grants: if grants_str.find(needed_grant) == -1: TestPymysqlUtils.err_msg = ''' User 'unittest' does not have the '%s' permission needed to run the tests. Need this in your MySQL: %s ''' % (needed_grant, 'GRANT %s ON unittest.* TO unittest@localhost;' % ','.join(needed_grants)) TestPymysqlUtils.env_ok = False return except (ValueError,RuntimeError): TestPymysqlUtils.err_msg = ''' For unit testing, localhost MySQL server must have user 'unittest' without password, and a database called 'unittest'. To create these prerequisites in MySQL: CREATE USER unittest@localhost; CREATE DATABASE unittest; This user needs permissions: %s ''' % 'GRANT %s ON unittest.* TO unittest@localhost;' % ','.join(needed_grants) TestPymysqlUtils.env_ok = False # Check MySQL version: try: (major, minor) = TestPymysqlUtils.get_mysql_version() except Exception as e: raise OSError('Could not get mysql version number: %s' % str(e)) if major is None: print('Warning: MySQL version number not found; testing as if V5.7') TestPymysqlUtils.major = 5 TestPymysqlUtils.minor = 7 else: TestPymysqlUtils.major = major TestPymysqlUtils.minor = minor known_versions = [(5,6), (5,7), (8,0)] if (major,minor) not in known_versions: print('Warning: MySQL version is %s.%s; but testing as if V5.7') TestPymysqlUtils.major = 5 TestPymysqlUtils.minor = 7