Add table "channels" + move some of the db functionas to module db.py

This commit is contained in:
Me 2020-12-21 23:52:18 +00:00
parent f4d704efa0
commit 0c0d8992b1
3 changed files with 631 additions and 207 deletions

93
srv/db.py Normal file
View file

@ -0,0 +1,93 @@
import os
from typing import List
from databases import Database
from sqlalchemy import (Column, DateTime, Integer, Float, String,
MetaData, Table, UniqueConstraint, create_engine)
import sqlalchemy
from sqlalchemy.sql import func
class EnergyDB():
def __init__(self, db_url : str):
self._engine = create_engine(db_url, connect_args={"check_same_thread": False})
# self.database = Database(db_url)
self._conn = self._engine.connect()
self._metadata = MetaData(self._engine)
self._tables = {
"energy": Table(
"energy", self._metadata,
Column("timestamp", DateTime, primary_key=True),
Column("channel_id", Integer(), nullable=False),
Column("value", Float),
UniqueConstraint("timestamp"),
),
"channels": Table(
"channels", self._metadata,
# Column("id", Integer(), autoincrement = True),
Column("id", Integer()), #, primary_key = True),
Column("name", String(), primary_key = True),
),
}
self._metadata.create_all(self._engine)
def metadata(self):
return self._metadata
def url(self):
return self._engine.url
def engine(self):
return self._engine
def table(self, name : str) -> sqlalchemy.Table:
return self._tables[name]
def execute(self, cmd, values = None, **args):
if values is None:
return self._conn.execute(cmd, args)
else:
return self._conn.execute(cmd, values, args)
return self._conn.execute(cmd, args)
def addChannels(self, channelNames: List[str]):
result = []
try:
# query = self.table("channels").insert()
query = sqlalchemy.sql.text("INSERT INTO channels (name) VALUES(:name)")
# nameDicts = [ {"name": name } for name in channelNames]
# result = self.execute(query, name=channelNames)
for n in channelNames:
result.append({"n": n})
self.execute(query, name=n)
except Exception as e:
raise Exception(f"Database error in addChannels(): {type(e)} - {str(e)}")
return {
"query": str(query),
"result": result,
# "result": [str(r) for r in result.fetchall()]
}
def getChannels(self) -> dict:
try:
table_channels = self.table("channels")
query = sqlalchemy.select([table_channels.c.name, table_channels.c.id]).select_from(table_channels)
channels = [dict(r.items()) for r in self.execute(query).fetchall()]
except Exception as e:
raise Exception(f"Database error in getChannels(): {type(e)} - {str(e)}")
return {
"channels": channels,
"query": str(query),
}
def getChannelId(self, channelName : str) -> int:
try:
query = sqlalchemy.sql.text(f"SELECT _ROWID_, name FROM channels WHERE name == :name")
chId = self.execute(query, name=channelName).scalar()
except Exception as e:
raise Exception(f"Database error in getChannelId(): {type(e)} - {str(e)}")
if chId is None:
raise Exception(f"Database error in getChannelId(): channel '{channelName}' not found")
return chId

View file

@ -1,42 +1,36 @@
from typing import Optional, List from typing import Optional, List, Dict
from fastapi import FastAPI, Header, HTTPException from fastapi import FastAPI, Header, HTTPException
from pydantic import BaseModel from pydantic import BaseModel
import datetime import datetime
import databases
import os import os
import sqlalchemy
from sqlite3 import OperationalError # import sqlalchemy
from .db import EnergyDB
import logging
API_VERSION_MAJOR = 1 API_VERSION_MAJOR = 1
API_VERSION_MINOR = 0 API_VERSION_MINOR = 0
REST_API_ROOT = f"/energy/v{API_VERSION_MAJOR}/" DB_URL = os.getenv("DATABASE_URL") #, default="sqlite://")
if len(DB_URL) == 0:
raise Exception("Environment variable DATABASE_URL missed!")
print(f"DB URL: {DB_URL}")
db = EnergyDB(DB_URL)
metadata = sqlalchemy.MetaData() app = FastAPI(debug=True)
energy = sqlalchemy.Table(
"energy",
metadata,
sqlalchemy.Column("timestamp", sqlalchemy.DateTime, primary_key=True),
sqlalchemy.Column("channel_id", sqlalchemy.Integer(), nullable=False),
sqlalchemy.Column("value", sqlalchemy.Float),
sqlalchemy.UniqueConstraint("timestamp"),
)
# DATABASE_URL = "sqlite:///./energyDB.sqlite" class InfoData(BaseModel):
DATABASE_URL = os.getenv("DATABASE_URL", default="sqlite://") info: Dict
print(f"DB URL: {DATABASE_URL}")
db = databases.Database(DATABASE_URL)
engine = sqlalchemy.create_engine(
DATABASE_URL,
connect_args={"check_same_thread": False})
metadata.create_all(engine)
class EnergyValue(BaseModel): class EnergyValue(BaseModel):
timestamp: datetime.datetime timestamp: datetime.datetime
value: float value: float
class ChannelData(BaseModel): class ChannelData(BaseModel):
channel_id: int channel_id: Optional[int]
channel: Optional[str]
data: List[EnergyValue] data: List[EnergyValue]
msg: Optional[str] msg: Optional[str]
@ -49,80 +43,246 @@ class BulkDataRequest(BaseModel):
fromTime: datetime.datetime fromTime: datetime.datetime
tillTime: datetime.datetime = datetime.datetime.now() tillTime: datetime.datetime = datetime.datetime.now()
app = FastAPI(debug=True) class ChannelInfo(BaseModel):
name: str
@app.on_event("startup") class Channels(BaseModel):
async def startup(): channels: List[ChannelInfo]
"""On startup connect to the database"""
await db.connect()
@app.on_event("shutdown") def _restApiPath(subPath : str) -> str:
async def shutdown(): """Return the full REST API path
"""On shutdow diconnect from the database"""
await db.disconnect()
# def _raiseHttpExceptionOnWrongToken(token : str): Arguments:
# if token != fake_secret_token: subPath {str} -- The sub-URL
# raise HTTPException(status_code=400, detail="Invalid X-Token header")
@app.put(REST_API_ROOT + "bulkData") Returns:
async def putBulkEnergyData(bulkData: BulkData): str -- The full REST API URL
valuesToInsert = [] """
for channelData in bulkData.bulk: REST_API_ROOT = f"/energy/v{API_VERSION_MAJOR}"
for measurement in channelData.data: if (subPath.startswith("/")):
valuesToInsert.append({ return REST_API_ROOT + subPath
"channel_id": channelData.channel_id, else:
"timestamp": measurement.timestamp, return REST_API_ROOT + "/" + subPath
"value": measurement.value})
query = energy.insert().values(valuesToInsert) @app.get(_restApiPath("/version"))
result = await db.execute(query) async def restApiGetVersion() -> dict:
"""Return the version information
Returns:
dict -- The version information of energyDB and SQLAlchemy
"""
return { return {
"valuesToInsert": valuesToInsert "version": f"{API_VERSION_MAJOR}.{API_VERSION_MINOR}",
} }
@app.get(REST_API_ROOT + "bulkData", response_model = BulkData) @app.get(_restApiPath("/info"), response_model = InfoData)
async def apiGetInfo():
info = {}
info["db_url"] = db.url()
e = sqlalchemy.Table("energy", db.metadata(), autoload=True, autoload_with=db.engine())
info["db_fields"] = [c.name for c in e.columns]
result = db.execute("select * from energy")
info["db_dir"] = str(dir(db))
info["result_type"] = str(type(result))
info["result_dir"] = str(dir(result))
info["result_count"] = str(result.rowcount)
info["db_contents"] = [str(row) for row in result.fetchall()]
result = db.execute("SELECT name FROM sqlite_master WHERE type='table'")
info["tables"] = [str(row) for row in result.fetchall()]
result = db.execute("SELECT sql FROM sqlite_master WHERE type='table'")
info["energy.sql"] = str(result.fetchone()[0]).replace("\n", "").replace("\t","")
result = db.execute("SELECT COUNT(*) FROM energy")
info["rows"] = str(result.fetchone())
# info["rows"] = [str(row) for row in result.fetchall()]
info["tables"] = [t.name for t in db.metadata().sorted_tables]
for t in db.metadata().sorted_tables:
# info[f"columns_{t}"] = str(dir(t))
info[f"columns_{t}"] = t.schema
return {
"info": info
}
@app.get(_restApiPath("/bulkData"), response_model = BulkData)
async def getBulkEnergyData(bulkDataRequest: BulkDataRequest): async def getBulkEnergyData(bulkDataRequest: BulkDataRequest):
bulkData = [] bulkData = []
for ch in bulkDataRequest.channel_ids: trace = []
query = sqlalchemy.select([energy.c.timestamp, energy.c.value]) \ exception = None
.where(energy.c.channel_id == ch) \ try:
.where(energy.c.timestamp >= bulkDataRequest.fromTime) \ for ch in bulkDataRequest.channel_ids:
.where(energy.c.timestamp <= bulkDataRequest.tillTime) data = []
try: table_energy = db.table("energy")
data = await db.fetch_all(query) query = sqlalchemy.select([table_energy.c.timestamp, table_energy.c.value]) \
.select_from(table_energy) \
.where(sqlalchemy.sql.and_(
table_energy.c.channel_id == ch,
table_energy.c.timestamp >= bulkDataRequest.fromTime,
table_energy.c.timestamp <= bulkDataRequest.tillTime
)
)
for row in db.execute(query).fetchall():
data.append(dict(row.items()))
bulkData.append({"channel_id": ch, "data": data}) bulkData.append({"channel_id": ch, "data": data})
except OperationalError as e: except Exception as e:
raise HTTPException(status_code=500, detail="Database error") raise HTTPException(
status_code=404,
detail=f"Database error: {type(e)} - {str(e)}"
# detail=f"Database error: {str(e)}\nQuery: {str(query)}"
)
return { return {
"bulk": bulkData, "bulk": bulkData,
"msg": __name__ + " - " +str(query.compile()) "msg": None #__name__ + " - " + str(query)
}
@app.get("/energy/{channel_id}", response_model = ChannelData)
async def getChannelData(channel_id: int):
try:
query = sqlalchemy.select([energy.c.timestamp, energy.c.value]).where(energy.c.channel_id == channel_id)
result = await db.fetch_all(query)
return {
"channel_id": channel_id,
"data": result
}
except Exception as ex:
raise HTTPException(status_code=500, detail=f"Internal error: {type(ex)} - \"{ex}\"")
@app.put("/energy/{channel_id}") #, response_model = EnergyValue)
async def putChannelData(channel_id: int, data: EnergyValue):
query = energy.insert().values(
timestamp=data.timestamp,
channel_id=channel_id,
value=data.value)
result = await db.execute(query)
# # return await db.fetch_all(query)
return {
"timestamp": datetime.datetime.now(),
# "channel" : data.channel,
"value": data.value,
"msg": str(result)
} }
@app.put(_restApiPath("/bulkData"))
async def putBulkEnergyData(bulkData: BulkData):
valuesToInsert = []
result = "ok"
# rows_before = {}
# rows_after = {}
try:
# rowCounter = 0
# dbResult = db.execute( db.tables["energy"].select() )
# for row in dbResult.fetchall():
# rows_before[f"row_{rowCounter}"] = str(row)
# rowCounter += 1
for channelData in bulkData.bulk:
if channelData.channel_id is None:
try:
table_channels = db.table("channels")
channel_id = db.execute(
sqlalchemy.select([table_channels.c.id]) \
.select_from(table_channels) \
.where(table_channels.c.name == channelData.channel))
except:
raise HTTPException(
status_code = 500,
detail = f"Database error: {type(ex)} - \"{ex}\""
)
for measurement in channelData.data:
valuesToInsert.append({
"channel_id": channelData.channel_id,
"timestamp": measurement.timestamp,
"value": measurement.value
})
db.execute(db.table("energy").insert(), valuesToInsert)
# rowCounter = 0
# dbResult = db.execute( db.tables["energy"].select() )
# for row in dbResult.fetchall():
# rows_after[f"row_{rowCounter}"] = str(row)
# rowCounter += 1
except Exception as e:
result = f"Exception \"{str(e)}\""
return {
"result": result,
# "rows_before": rows_before,
# "rows_after": rows_after,
}
@app.put(_restApiPath("/channels"))
async def putChannels(channel_info: Channels):
result = "ok"
query = "???"
rows_before = {}
rows_after = {}
try:
r = db.getChannels()
rows_before = r["channels"]
channelNames = [c.name for c in channel_info.channels]
res = db.addChannels(channelNames)
result = res["result"]
query = res["query"]
r = db.getChannels()
rows_after = r["channels"]
except Exception as e:
result = f"Exception \"{str(e)}\""
return {
"result": result,
"channels": str(channel_info.channels),
"channelNames": channelNames,
"query": query,
"rows_before": rows_before,
"rows_after": rows_after,
}
@app.get(_restApiPath("/channels"))
async def getChannels() -> dict:
"""Return a list of all channels
Raises:
HTTPException: with status 500 on a database error
Returns:
dict -- the list of all channels
"""
try:
result = db.getChannels()
return {"channels": [ch["name"] for ch in result["channels"]]}
except Exception as e:
raise HTTPException(status_code = 500, detail = str(e))
@app.get(_restApiPath("/channels/{channel}/id"))
async def getChannelId(channel: str): # -> dict:
try:
chId = db.getChannelId(channel)
return {
"channel": channel,
"id": chId,
# "query": str(r["query"])
}
except Exception as e:
raise HTTPException(status_code=500,detail=f"Database error: {type(e)} - {str(e)}")
# @app.get("/energy/{channel_id}", response_model = ChannelData)
# async def getChannelData(channel_id: int):
# try:
# query = sqlalchemy.select([energy.c.timestamp, energy.c.value]).where(energy.c.channel_id == channel_id)
# result = await db.fetch_all(query)
# return {
# "channel_id": channel_id,
# "data": result
# }
# except Exception as ex:
# raise HTTPException(status_code=500, detail=f"Internal error: {type(ex)} - \"{ex}\"")
# @app.put("/energy/{channel_id}") #, response_model = EnergyValue)
# async def putChannelData(channel_id: int, data: EnergyValue):
# query = energy.insert().values(
# timestamp=data.timestamp,
# channel_id=channel_id,
# value=data.value)
# result = await db.execute(query)
# # # return await db.fetch_all(query)
# return {
# "timestamp": datetime.datetime.now(),
# # "channel" : data.channel,
# "value": data.value,
# "msg": str(result)
# }
@app.get(_restApiPath("/{channel_id}/count")) # response_model = ChannelData)
async def getChannelRowCount(channel_id: int):
info = {}
info["columns"] = str( db.table("energy").columns)
# countQuery = sqlalchemy.select([sqlalchemy.func.count()]).select_from(db.tables["energy"])
# info["stmt"] = str(countQuery)
# countResult = db.execute( countQuery )
# info["count"] = countResult.fetchone()[0]
# info["tables"] = [t.name for t in metadata.sorted_tables]
# for t in metadata.tables:
# info[f"columns_{t}"] = str(type(t))
# # info[f"columns_{t}"] = list(sqlalchemy.inspect(t).columns)
return { "info": info }

View file

@ -9,143 +9,314 @@ import urllib.parse
#TODO Use in-memory DB to test the case that there is no table #TODO Use in-memory DB to test the case that there is no table
#TODO Add helper function to fill the in-memory DB before test #TODO Add helper function to fill the in-memory DB before test
os.environ["DATABASE_URL"] = "sqlite:///./energyDB.sqlite" # os.environ["DATABASE_URL"] = "sqlite:///./testDB.sqlite"
os.environ["DATABASE_URL"] = "sqlite://"
from srv import energyDB from srv import energyDB
class Test_energyDb: class Test_energyDB:
restApiRoot = "/energy/v1/" restApiRoot = "/energy/v1"
bulkTestData = [ testData = {
{ "channels": (
"channel_id": 1, {"name": "dc_power1"},
"data": ( {"name": "daily_yield"},
{ "timestamp": "2020-12-11T12:00:22", "value": 1100.1 }, {"name": "total_yield"},
{ "timestamp": "2020-12-11T12:10:15", "value": 1109.2 }, ),
{ "timestamp": "2020-12-11T12:20:13", "value": 1119.3 }, "bulkdata": (
{ "timestamp": "2020-12-11T12:30:21", "value": 1131.4 }, {
{ "timestamp": "2020-12-11T12:40:08", "value": 1143.5 }, "channel_id": 1,
{ "timestamp": "2020-12-11T12:50:13", "value": 1152.6 }, "data": (
{ "timestamp": "2020-12-11T13:00:11", "value": 1160.7 }, { "timestamp": "2020-12-11T12:00:22", "value": 1100.1 },
{ "timestamp": "2020-12-11T13:10:09", "value": 1169.8 }, { "timestamp": "2020-12-11T12:10:15", "value": 1109.2 },
{ "timestamp": "2020-12-11T13:20:10", "value": 1181.9 }, { "timestamp": "2020-12-11T12:20:13", "value": 1119.3 },
{ "timestamp": "2020-12-11T13:30:17", "value": 1190.0 }, { "timestamp": "2020-12-11T12:30:21", "value": 1131.4 },
) { "timestamp": "2020-12-11T12:40:08", "value": 1143.5 },
}, { "timestamp": "2020-12-11T12:50:13", "value": 1152.6 },
{ { "timestamp": "2020-12-11T13:00:11", "value": 1160.7 },
"channel_id": 2, { "timestamp": "2020-12-11T13:10:09", "value": 1169.8 },
"data": [ { "timestamp": "2020-12-11T13:20:10", "value": 1181.9 },
{ "timestamp": "2020-12-11T12:01:15", "value": 1200.1 }, { "timestamp": "2020-12-11T13:30:17", "value": 1190.0 },
{ "timestamp": "2020-12-11T12:21:28", "value": 1219.2 }, )
{ "timestamp": "2020-12-11T12:41:21", "value": 1243.3 }, },
{ "timestamp": "2020-12-11T13:01:16", "value": 1260.4 }, {
{ "timestamp": "2020-12-11T13:21:18", "value": 1281.5 }, "channel_id": 2,
] "data": [
} { "timestamp": "2020-12-11T12:01:15", "value": 1200.1 },
] { "timestamp": "2020-12-11T12:21:28", "value": 1219.2 },
{ "timestamp": "2020-12-11T12:41:21", "value": 1243.3 },
{ "timestamp": "2020-12-11T13:01:16", "value": 1260.4 },
{ "timestamp": "2020-12-11T13:21:18", "value": 1281.5 },
]
}
)
}
client = TestClient(energyDB) # client = TestClient(energyDB)
# def setup(self): def setup(self):
# self.client = TestClient(energyDB) self.client = TestClient(energyDB)
# def teardown(self): def teardown(self):
# self.client = None self.client = None
def _test_bulkData_put(self): # --- helper functions
# response = self.client.put("/energy/bulkData", json=self.bulkTestData);
def _apiUrl(self, sub_url : str):
if sub_url.startswith("/"):
return self.restApiRoot + sub_url
else:
return self.restApiRoot + "/" + sub_url
def _fillDatabase(self):
response = self.client.put( response = self.client.put(
self.restApiRoot + "bulkData", self._apiUrl("/channels"),
json={"bulk": self.bulkTestData}) json = {"channels": self.testData["channels"]}
# print(f"dir(response): {dir(response)}") )
# print(f"dir(response.request): {dir(response.request)}") # self._dumpRequestAndResponse("_fillDatabase(channels)", response)
# print("---- request")
# print(f"response.request.method: {response.request.method}")
# print(f"response.request.url: {urllib.parse.unquote(response.request.url)}")
# print(f"response.request.headers: {response.request.headers}")
# requestJson = json.loads(response.request.body)
# print(f"response.request.body: {json.dumps(requestJson, indent=2)}")
print("---- response")
print(f"response.reason: {response.reason}")
responseJson = json.loads(response.text)
print(f"response.text: {json.dumps(responseJson, indent=2)}")
# print(f"response.text: {json.dumps(response.text, indent=2)}")
assert response.status_code == 200 assert response.status_code == 200
def test_bulkData_get(self): response = self.client.put(
print(f"DB_URL: {os.getenv('DATABASE_URL')}") self._apiUrl("/bulkData"),
# response = self.client.put("/energy/bulkData", json=self.bulkTestData); json = {"bulk": self.testData["bulkdata"]}
fromTimestamp = datetime.fromisoformat("2020-12-11T12:30:00") )
tillTimestamp = datetime.fromisoformat("2020-12-11T12:30:59") # self._dumpRequestAndResponse("_fillDatabase(data)", response)
response = self.client.get( assert response.status_code == 200
self.restApiRoot + "bulkData",
json = { def _dumpRequestAndResponse(self, context : str, response):
"channel_ids": [1, 2, 3], print("\n")
"fromTime": fromTimestamp.isoformat(), print(f"---- request ({context})")
# "tillTime": tillTimestamp.isoformat()
})
# print(f"dir(response): {dir(response)}")
# print(f"dir(response.request): {dir(response.request)}")
print("---- request")
print(f"response.request.method: {response.request.method}") print(f"response.request.method: {response.request.method}")
print(f"response.request.url: {urllib.parse.unquote(response.request.url)}") print(f"response.request.url: {urllib.parse.unquote(response.request.url)}")
print(f"response.request.headers: {response.request.headers}") print(f"response.request.headers: {response.request.headers}")
print(f"dir(response.request): {dir(response.request)}") try:
print(f"response.request.body: {response.request.body}") requestJson = json.loads(response.request.body)
# requestJson = json.loads(response.request.body) print(f"response.request.body(json): {json.dumps(requestJson, indent=2)}")
# print(f"response.request.body: {json.dumps(requestJson, indent=2)}") except:
print("---- response") print(f"response.request.body(plain): {response.request.body}")
print(f"---- response ({context})")
print(f"response.status_code: {response.status_code}")
print(f"response.reason: {response.reason}") print(f"response.reason: {response.reason}")
responseJson = json.loads(response.text) try:
print(f"response.text: {json.dumps(responseJson, indent=2)}") responseJson = json.loads(response.text)
# print(f"response.text: {json.dumps(response.text, indent=2)}") print(f"response.text(json): {json.dumps(responseJson, indent=2)}")
except:
print(f"response.text(plain): {response.text}")
# --- test functions
def test_invalidRoute(self):
response = self.client.get("/")
assert response.status_code == 404
def test_getVersion(self):
response = self.client.get(self._apiUrl("/version"))
# self._dumpRequestAndResponse("test_getVersion", response)
assert response.status_code == 200
assert response.json()["version"] == "1.0"
def _test_getInfo(self):
response = self.client.get( self._apiUrl("/info" ))
# self._dumpRequestAndResponse("test_getInfo", response)
assert response.status_code == 200 assert response.status_code == 200
@pytest.mark.skip(reason="Ignore me temporarily") def _test_getChannelsOfEmptyTable(self):
def test_insert_energy(self): response = self.client.get(self._apiUrl("/channels"))
energyData = { # self._dumpRequestAndResponse("test_getChannelsOfEmptyTable", response)
"timestamp": datetime.now().isoformat(), assert response.status_code == 200
"value": 234.5, assert response.json()["channels"] == []
}
print(f"energyData: {energyData}") def _test_getBulkDataOfEmptyTable(self):
# response = self.client.put("/energies/1", json=energyData) #, headers={"X-Token": "coneofsilence"}) response = self.client.get(
self._apiUrl("/bulkData"),
json = {
"channel_ids": [1],
"fromTime": "0001-01-01T00:00:00"
}
)
self._dumpRequestAndResponse("test_getBulkDataOfEmptyTable", response)
assert response.status_code == 200
assert "bulk" in response.json()
assert response.json()["bulk"] == [
{
"channel_id": 1,
"channel": None,
"data": [],
"msg": None
}
]
def test_fillDatabase(self):
self._fillDatabase()
response = self.client.get(self._apiUrl("/1/count"))
# self._dumpRequestAndResponse("test_fillDatabase", response)
assert response.status_code == 200
def test_getChannels(self):
response = self.client.get(self._apiUrl("/channels"))
# self._dumpRequestAndResponse("test_getChannels", response)
assert response.status_code == 200
def test_getChannelId(self):
response = self.client.get(self._apiUrl("/channels/total_yield/id"))
# self._dumpRequestAndResponse("test_getChannelId", response)
assert response.status_code == 200
response = self.client.get(self._apiUrl("/channels/dc_power1/id"))
# self._dumpRequestAndResponse("test_getChannelId", response)
assert response.status_code == 200
response = self.client.get(self._apiUrl("/channels/daily_yield/id"))
# self._dumpRequestAndResponse("test_getChannelId", response)
assert response.status_code == 200
def test_putChannels(self):
response = self.client.get(self._apiUrl("/channels/frequency/id"))
# self._dumpRequestAndResponse("test_getChannelId", response)
assert response.status_code == 500
response = self.client.put( response = self.client.put(
self.restApiRoot + "2", self._apiUrl("/channels"),
# params=energyData, json = {"channels": [{"name": "frequency"}]}
json=energyData) #, headers={"X-Token": "coneofsilence"}) )
# print(f"dir(response): {dir(response)}") # self._dumpRequestAndResponse("test_fillDatabase", response)
# print(f"dir(response.request): {dir(response.request)}")
# print("---- request")
# print(f"response.request.method: {response.request.method}")
# print(f"response.request.url: {urllib.parse.unquote(response.request.url)}")
# print(f"response.request.headers: {response.request.headers}")
# print(f"response.request.body: {json.loads(response.request.body)}")
# print("---- response")
# print(f"response.reason: {response.reason}")
# print(f"response.text: {json.loads(response.text)}")
# print(f"request.header: \"{response.request.header}\"")
# print(f"request.body: \"{response.request.body}\"")
assert response.status_code == 200 assert response.status_code == 200
# assert response.json()["msg"] == ""
@pytest.mark.skip(reason="Ignore me temporarily") response = self.client.get(self._apiUrl("/channels/frequency/id"))
def test_get_energy(self): # self._dumpRequestAndResponse("test_getChannelId", response)
response = self.client.get(self.restApiRoot + "1")
# print(f"dir(response): {dir(response)}")
# print(f"dir(response.request): {dir(response.request)}")
# print("---- request")
# print(f"response.request.method: {response.request.method}")
# print(f"response.request.url: {urllib.parse.unquote(response.request.url)}")
# print(f"response.request.headers: {response.request.headers}")
# print("---- response")
# print(f"response.reason: {response.reason}")
responseJson = json.loads(response.text)
print(f"response.text: {json.dumps(responseJson, indent=2)}")
data = response.json()
# print(f"data: {type(data)}")
# for k,v in data.items():
# print(f"key: {k} -> value: {v}")
print(f"data of channel: {data['channel_id']}")
for r in data["data"]:
print(f"r: {r}")
assert response.status_code == 200 assert response.status_code == 200
# assert response.json()["msg"] == ""
def _test_putBulkData(self):
response = self.client.put(
self._apiUrl("/bulkData"),
json = {"bulk": {
"channel_id": None,
"channel": "total_yield",
"data": [
{ "timestamp": "2020-12-11T12:01:20", "value": 120120.1 },
{ "timestamp": "2020-12-11T12:30:25", "value": 123025.2 },
]
}}
)
self._dumpRequestAndResponse("test_putBulkData", response)
assert response.status_code == 200
# def test_getRecordCount(self):
# response = self.client.get(self._apiUrl("/1/count"))
# self._dumpRequestAndResponse("test_getRecordCount", response)
# assert response.status_code == 200
# assert response.json()["info"] == {"columns"}
# def _test_bulkData_put(self):
# # response = self.client.put("/energy/bulkData", json=self.bulkTestData);
# response = self.client.put(
# self.restApiRoot + "bulkData",
# json={"bulk": self.bulkTestData})
# # print(f"dir(response): {dir(response)}")
# # print(f"dir(response.request): {dir(response.request)}")
# # print("---- request")
# # print(f"response.request.method: {response.request.method}")
# # print(f"response.request.url: {urllib.parse.unquote(response.request.url)}")
# # print(f"response.request.headers: {response.request.headers}")
# # requestJson = json.loads(response.request.body)
# # print(f"response.request.body: {json.dumps(requestJson, indent=2)}")
# print("---- response")
# print(f"response.reason: {response.reason}")
# responseJson = json.loads(response.text)
# print(f"response.text: {json.dumps(responseJson, indent=2)}")
# # print(f"response.text: {json.dumps(response.text, indent=2)}")
# assert response.status_code == 200
# def _test_getInfo2(self):
# response = self.client.get( self.restApiRoot + "info" )
# # print(f"dir(response): {dir(response)}")
# # print(f"dir(response.request): {dir(response.request)}")
# print("---- request")
# print(f"response.request.method: {response.request.method}")
# print(f"response.request.url: {urllib.parse.unquote(response.request.url)}")
# print(f"response.request.headers: {response.request.headers}")
# # print(f"dir(response.request): {dir(response.request)}")
# print("---- response")
# print(f"response.reason: {response.reason}")
# # print(f"response.text: {response.text}")
# responseJson = json.loads(response.text)
# print(f"response.text: {json.dumps(responseJson, indent=2)}")
# assert False #response.status_code == 404
# def _test_bulkData_get(self):
# print(f"DB_URL: {os.getenv('DATABASE_URL')}")
# # response = self.client.put("/energy/bulkData", json=self.bulkTestData);
# fromTimestamp = datetime.fromisoformat("2020-12-11T12:30:00")
# tillTimestamp = datetime.fromisoformat("2020-12-11T12:30:59")
# response = self.client.get(
# self.restApiRoot + "bulkData",
# json = {
# "channel_ids": [1, 2, 3],
# "fromTime": fromTimestamp.isoformat(),
# # "tillTime": tillTimestamp.isoformat()
# })
# # print(f"dir(response): {dir(response)}")
# # print(f"dir(response.request): {dir(response.request)}")
# print("---- request")
# print(f"response.request.method: {response.request.method}")
# print(f"response.request.url: {urllib.parse.unquote(response.request.url)}")
# print(f"response.request.headers: {response.request.headers}")
# print(f"dir(response.request): {dir(response.request)}")
# print(f"response.request.body: {response.request.body}")
# # requestJson = json.loads(response.request.body)
# # print(f"response.request.body: {json.dumps(requestJson, indent=2)}")
# print("---- response")
# print(f"response.reason: {response.reason}")
# responseJson = json.loads(response.text)
# print(f"response.text: {json.dumps(responseJson, indent=2)}")
# # print(f"response.text: {json.dumps(response.text, indent=2)}")
# assert response.status_code == 200
# @pytest.mark.skip(reason="Ignore me temporarily")
# def test_insert_energy(self):
# energyData = {
# "timestamp": datetime.now().isoformat(),
# "value": 234.5,
# }
# print(f"energyData: {energyData}")
# # response = self.client.put("/energies/1", json=energyData) #, headers={"X-Token": "coneofsilence"})
# response = self.client.put(
# self.restApiRoot + "2",
# # params=energyData,
# json=energyData) #, headers={"X-Token": "coneofsilence"})
# # print(f"dir(response): {dir(response)}")
# # print(f"dir(response.request): {dir(response.request)}")
# # print("---- request")
# # print(f"response.request.method: {response.request.method}")
# # print(f"response.request.url: {urllib.parse.unquote(response.request.url)}")
# # print(f"response.request.headers: {response.request.headers}")
# # print(f"response.request.body: {json.loads(response.request.body)}")
# # print("---- response")
# # print(f"response.reason: {response.reason}")
# # print(f"response.text: {json.loads(response.text)}")
# # print(f"request.header: \"{response.request.header}\"")
# # print(f"request.body: \"{response.request.body}\"")
# assert response.status_code == 200
# # assert response.json()["msg"] == ""
# @pytest.mark.skip(reason="Ignore me temporarily")
# def test_get_energy(self):
# response = self.client.get(self.restApiRoot + "1")
# # print(f"dir(response): {dir(response)}")
# # print(f"dir(response.request): {dir(response.request)}")
# # print("---- request")
# # print(f"response.request.method: {response.request.method}")
# # print(f"response.request.url: {urllib.parse.unquote(response.request.url)}")
# # print(f"response.request.headers: {response.request.headers}")
# # print("---- response")
# # print(f"response.reason: {response.reason}")
# responseJson = json.loads(response.text)
# print(f"response.text: {json.dumps(responseJson, indent=2)}")
# data = response.json()
# # print(f"data: {type(data)}")
# # for k,v in data.items():
# # print(f"key: {k} -> value: {v}")
# print(f"data of channel: {data['channel_id']}")
# for r in data["data"]:
# print(f"r: {r}")
# assert response.status_code == 200
# # assert response.json()["msg"] == ""