'''
Created on 2020-09-12
@author: wf
'''
import unittest
from tests.basetest import Basetest
import json
from lodstorage.sample import Royals,RoyalsORMList,Royal,Cities
from lodstorage.jsonable import JSONAble, Types, JSONAbleList
import time
import tempfile
[docs]class ServerConfig(JSONAble):
def __init__(self):
pass
[docs]class TestJsonAble(Basetest):
'''
test JSON serialization with JsonAble mixin
'''
[docs] def setUp(self):
super().setUp(debug=False)
self.doProfile=True
self.maxDiff=None
pass
[docs] def testSingleToDoubleQuote(self):
jsonStr='''
{
"cities": [
{
"name": "Upper Hell's Gate"
},
{
"name": "N'zeto"
}
]
}
'''
listOfDicts=json.loads(jsonStr)
dictStr=str(listOfDicts)
if self.debug:
print(dictStr)
jsonStr2=JSONAble.singleQuoteToDoubleQuote(dictStr)
if self.debug:
print(jsonStr2)
self.assertEqual('''{"cities": [{"name": "Upper Hell's Gate"}, {"name": "N'zeto"}]}''',jsonStr2)
[docs] def testSingleQuoteToDoubleQuoteStackoverflow(self):
"""
see
- https://stackoverflow.com/a/63862387/1497139
- https://stackoverflow.com/a/50257217/1497139
"""
singleQuotedExamples=[
'''{'cities': [{'name': "Upper Hell's Gate"}, {'name': "N'zeto"}]''']
for example in singleQuotedExamples:
if self.debug:
print (example)
for useRegex in [False,True]:
doubleQuoted=JSONAble.singleQuoteToDoubleQuote(example,useRegex=useRegex)
if self.debug:
print(doubleQuoted)
if self.debug:
print
[docs] def dumpListOfDicts(self,listOfDicts,limit):
if self.debug:
for index,record in enumerate(listOfDicts[:limit]):
print("%2d:%s" % (index,record))
[docs] def check(self,manager,manager1,listName,debugLimit):
'''
check that the list of the two managers are the same
'''
d1=manager.__dict__[listName]
d2=manager1.__dict__[listName]
self.dumpListOfDicts(d1, debugLimit)
self.dumpListOfDicts(d2, debugLimit)
self.assertEqual(d1,d2)
[docs] def testJsonAble(self):
'''
test JSONAble
'''
examples=[{
'manager': Royals(load=True),
'listName': 'royals'
}, {
'manager': Cities(load=True),
'listName': 'cities'
}
]
debugLimit=10
debugChars=debugLimit*100
index=0
for useToJson in [True,False]:
for example in examples:
starttime=time.time()
manager=example['manager']
listName=example['listName']
if useToJson:
jsonStr=manager.toJSON()
else:
jsonStr=manager.asJSON()
if self.debug:
print(jsonStr[:debugChars])
#print(jsonStr,file=open('/tmp/example%d.json' %index,'w'))
index+=1
if self.doProfile:
print("->JSON for %d took %7.3f s" % (index, (time.time()-starttime)))
self.assertTrue(isinstance(jsonStr,str))
starttime=time.time()
jsonDict=json.loads(jsonStr)
self.assertTrue(isinstance(jsonDict,dict))
if self.debug:
print(str(jsonDict)[:debugChars])
if self.doProfile:
print("<-JSON for %d took %7.3f s" % (index, time.time()-starttime))
cls=manager.__class__
types=Types(cls.__name__)
types.getTypes(listName,manager.__dict__[listName])
manager1=cls()
manager1.fromJson(jsonStr,types=types)
self.check(manager,manager1,listName,debugLimit=debugLimit)
pass
[docs] def testRoyals(self):
'''
test Royals example
'''
royals1=Royals(load=True)
self.assertEqual(4,len(royals1.royals))
json=royals1.toJSON()
if self.debug:
print(json)
types=Types.forTable(royals1, "royals",debug=True)
royals2=Royals()
royals2.fromJson(json,types=types)
self.assertEqual(4,len(royals2.royals))
if self.debug:
print(royals1.royals)
print(royals2.royals)
self.assertEqual(royals1.royals,royals2.royals)
[docs] def testPluralName(self):
royal=Royal()
self.assertEqual("Royals",royal.getPluralname())
[docs] def testStoreAndRestore(self):
'''
test storing and restoring from a JSON file
https://github.com/WolfgangFahl/pyLoDStorage/issues/21
'''
royals1=RoyalsORMList(load=True)
jsonFile="/tmp/royals-pylodstorage.json"
royals1.storeToJsonFile(jsonFile)
royals2=RoyalsORMList()
royals2.restoreFromJsonFile(jsonFile)
self.assertEqual(4,len(royals2.royals))
for royal in royals2.royals:
self.assertTrue(isinstance(royal,Royal))
self.assertEqual("float",type(royal.age).__name__)
[docs] def testIssue22(self):
'''
https://github.com/WolfgangFahl/pyLoDStorage/issues/22
Regression: storeToJsonFile and restoreFromJsonFile missing in JSONAble
'''
jsonStr="""{
"adminPassword": "tiger2021",
"adminUser": "scott",
"credentials": [
{
"dbname": "doedb",
"password": "doesSecret!",
"user": "john"
}
],
"frontendConfigs": [
{
"defaultPage": "Frontend",
"site": "or",
"template": "bootstrap.html",
"wikiId": "or"
},
{
"defaultPage": "Main Page",
"site": "cr",
"template": "bootstrap.html",
"wikiId": "cr"
}
],
"logo": "https://commons.wikimedia.org/wiki/Category:Mona_Lisa#/media/File:Mona_Lisa,_by_Leonardo_da_Vinci,_from_C2RMF_retouched.jpg"
}"""
jsonFilePath=f'{tempfile.gettempdir()}/serverConfig.json'
JSONAble.storeJsonToFile(jsonStr, jsonFilePath)
serverConfig=ServerConfig()
serverConfig.restoreFromJsonFile(jsonFilePath)
self.assertTrue(serverConfig.logo.endswith("_retouched.jpg"))
self.assertTrue(isinstance(serverConfig.frontendConfigs,list))
self.assertEqual(2,len(serverConfig.frontendConfigs))
serverConfig.storeToJsonFile(jsonFilePath)
jsonStr2=JSONAble.readJsonFromFile(jsonFilePath)
if self.debug:
print(jsonStr2)
self.assertEqual(jsonStr,jsonStr2)
[docs] def testRestoreFromJsonStr(self):
'''
Tests restoring a JsonAbleList form a json string
'''
samples = """
{
"countries": [
{
"name": "Afghanistan",
"wikidataid": "Q889",
"coordinates": "34,66",
"partOf": null,
"level": 3,
"locationKind": "Country",
"comment": null,
"iso": "AF"
},
{
"name": "United States of America",
"wikidataid": "Q30",
"coordinates": "39.828175,-98.5795",
"partOf": null,
"level": 3,
"locationKind": "Country",
"comment": null,
"labels": [
"America",
"UNITED STATES OF AMERICA",
"USA",
"United States",
"United States of America (the)"
],
"iso": "US"
},
{
"name": "Australia",
"wikidataid": "Q408",
"coordinates": "-28,137",
"partOf": null,
"level": 3,
"locationKind": "Country",
"comment": null,
"labels": [
"AUS"
],
"iso": "AU"
}
]
}
"""
countryList=JSONAbleList("countries")
countryList.restoreFromJsonStr(samples)
countries=countryList.countries
self.assertTrue(len(countries)==3)
countryIds=[x['wikidataid'] for x in countries]
self.assertTrue("Q30" in countryIds)
[docs] def testIssue27_Lookup(self):
'''
add Lookup map option
'''
# first try with List of Dicts
royals=Royals(load=True)
#print(len(royals.royals))
#print(royals.royals)
royalsByNumberInLine,duplicates=royals.getLookup("numberInLine", withDuplicates=False)
#print(royalsByNumberInLine)
self.assertEqual(0,len(duplicates))
self.assertEqual(4,len(royalsByNumberInLine))
self.assertEqual("Charles, Prince of Wales",royalsByNumberInLine[1]["name"])
# then with list of Entities
royalsORM=RoyalsORMList(load=True)
royalsByNumberInLine,duplicates=royalsORM.getLookup("numberInLine", withDuplicates=False)
self.assertEqual(0,len(duplicates))
self.assertEqual(4,len(royalsByNumberInLine))
self.assertEqual("Charles, Prince of Wales",royalsByNumberInLine[1].name)
[docs] def testIssue30_SampleLimited(self):
'''
tests if the json export is correctly limited to the fields that are used in the samples
'''
royalDict={"name":"Test royal"}
royal=Royal()
royal.fromDict(royalDict)
# add attributes that are not in the samples
royal.__dict__["not_in_samples"]="test"
expectedJSON="""{
"name": "Test royal"
}"""
actualJSON=royal.toJSON(limitToSampleFields=True)
self.assertEqual(actualJSON, expectedJSON)
if __name__ == "__main__":
#import sys;sys.argv = ['', 'Test.testName']
unittest.main()