logservice.fetch() is not returning anything - python

The following code is used to fetch logs from app engine for further processing. However I do not know how to use the result of logservice.fetch to access log messages now??
import cgi
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
from google.appengine.api.logservice import logservice
logservice.AUTOFLUSH_ENABLED = False
class MainPage(webapp.RequestHandler):
def get(self):
requestlogs = logservice.fetch(start_time=1332200000, end_time=1332249954, offset=None, minimum_log_level=logservice.LOG_LEVEL_INFO, include_incomplete=False, include_app_logs=True, version_ids=None, batch_size=None)
self.response.out.write(requestlogs)
c=0
for iter in requestlogs:
c=c+1
print c
application = webapp.WSGIApplication([('/logs', MainPage)], debug=True)
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()

In your case, the code would look something like this:
from google.appengine.api import logservice
MAX_LOGS_TO_READ = 10
class MainPage(webapp.RequestHandler):
def get(self):
request_logs = logservice.fetch()
current_log = 0
for log in request_logs:
if current_log > MAX_LOGS_TO_READ:
break
self.response.out.write(log.combined)
A couple of comments..
Use self.response.out.write() to write data to the response output stream.
fetch() returns an iterator of RequestLog objects. You can use this iterator then in a for loop to go over the set of logs the iterator knows about.
RequestLog objects return a number of attributes, which are mostly documented here: http://code.google.com/appengine/docs/python/logservice/requestlogclass.html

Related

how to do unit test for functions inside of Resource class in flask-restful?

I am quite new to unit testing and relatively new to RESTful API development as well. I am wondering how to do unit test for functions inside Resource class in flask restful? I can do unit test for the endpoint's response but I don't know how to do testing for the individual functions inside the endpoint's controller class.
Below is my application code. It has 3 files including test:
api.py
controller_foo.py
test_controller_foo.py
# api.py
from flask import Flask
from flask_restful import Api
from .controller_foo import ControllerFoo
def create_app(config=None):
app = Flask(__name__)
app.config['ENV'] ='development'
return app
application = app = create_app()
api = Api(app)
api.add_resource(ControllerFoo, '/ctrl')
if __name__ == "__main__":
app.run(debug=True)
# controller_foo.py
from flask_restful import Resource
from flask import request
class ControllerFoo(Resource):
"""
basically flask-restful's Resource method is a wrapper for flask's MethodView
"""
def post(self):
request_data = self.handle_request()
response = self.process_request(request_data)
return response
def handle_request(self):
json = request.get_json()
return json
def process_request(self, data):
# do some stuffs here
return {'foo': 'bar'}
I am using unittest
# test_controller_foo.py
import unittest
from api import app
from .controller_foo import ControllerFoo
# initiating class to try testing but I don't know how to start
ctrl = ControllerFoo()
class ControllerFooTestCase(unittest.TestCase):
def setUp(self):
self.app = app
self.app.config['TESTING'] = True
self.client = app.test_client()
self.payload = {'its': 'empty'}
def tearDown(self):
pass
def test_get_response(self):
response = self.client.post('/ctrl', json=self.payload)
expected_resp = {
'foo': 'bar'
}
self.assertEqual(response.status_code, 200)
self.assertDictEqual(response.get_json(), expected_resp)
if __name__ == "__main__":
unittest.main()
I want to know how to properly do unit test for handle_request and process_request function
EDIT: Fixing out my buggy code. Thanks Laurent LAPORTE for the highlights.
There are several bugs in your code, so this is not easy to explain.
First of all, the recommended way to do testing with Flask (and Flask-Restful) is to use PyTest instead of unittest, because it is easier to setup and use.
Take a look at the documentation: Testing Flask Applications.
But, you can start with unittest…
note: you can have a confusion with your app module and the app instance in that module. So, to avoid it, I imported the module. Another good practice is to name your test module against the tested module: "app.py" => "test_app.py". You can also have a confusion with the controller module and the controller instance. The best practice is to use a more precise name, like "controller_foo" or something else…
Here is a working unit test:
# test_app.py
import unittest
import app
class ControllerTestCase(unittest.TestCase):
def setUp(self):
self.app = app.app
self.app.config['TESTING'] = True
self.client = self.app.test_client()
self.payload = {'its': 'empty'}
def test_get_response(self):
response = self.client.post('/ctrl', json=self.payload)
expected_resp = {'foo': 'bar'}
self.assertEqual(response.status_code, 200)
self.assertDictEqual(response.get_json(), expected_resp)
if __name__ == "__main__":
unittest.main()
As you can see, I also fixed the posted URL, in your application, the URL is "/ctrl", not "controller".
At this point, the test can run, but you have another error:
Ran 1 test in 0.006s
FAILED (errors=1)
Error
Traceback (most recent call last):
...
TypeError: process_request() takes 1 positional argument but 2 were given
If you take a look at your process_request() method, you can see that you missed the self parameter. Change it like this.
def process_request(self, data):
# do some stuffs here
return {'foo': 'bar'}
Your test should pass.
But, that not the right way to implement Flask-Restful controolers. Read the doc and use get and post methods…

Mock database connection python

I have a file called redis_db.py which has code to connect to redis
import os
import redis
import sys
class Database:
def __init__(self, zset_name):
redis_host = os.environ.get('REDIS_HOST', '127.0.0.1')
redis_port = os.environ.get('REDIS_PORT', 6379)
self.db = redis.StrictRedis(host=redis_host, port=redis_port)
self.zset_name = zset_name
def add(self, key):
try:
self.db.zadd(self.zset_name, {key: 0})
except redis.exceptions.ConnectionError:
print("Unable to connect to redis host.")
sys.exit(0)
I have another file called app.py which is like this
from flask import Flask
from redis_db import Database
app = Flask(__name__)
db = Database('zset')
#app.route('/add_word/word=<word>')
def add_word(word):
db.add(word)
return ("{} added".format(word))
if __name__ == '__main__':
app.run(host='0.0.0.0', port='8080')
Now I am writing unit test for add_word function like this
import unittest
import sys
import os
from unittest import mock
sys.path.append(os.path.dirname(os.path.realpath(__file__)) + "/../api/")
from api import app # noqa: E402
class Testing(unittest.TestCase):
def test_add_word(self):
with mock.patch('app.Database') as mockdb:
mockdb.return_value.add.return_value = ""
result = app.add_word('shivam')
self.assertEqual(result, 'shivam word added.')
Issue I am facing is that even though I am mocking the db method call it is still calling the actual method in the class instead of returning mocked values and during testing I am getting error with message Unable to connect to redis host..
Can someone please help me in figuring out how can I mock the redis database calls.
I am using unittest module
The issue is that db is defined on module import, so the mock.patch does not affect the db variable. Either you move the instantiation of
db in the add_word(word) function or you patch db instead of Database, e.g.
def test_add_word():
with mock.patch('api.app.db') as mockdb:
mockdb.add = mock.MagicMock(return_value="your desired return value")
result = app.add_word('shivam')
print(result)
Note that the call of add_word has to be in the with block, otherwise the unmocked version is used.

python flask before_first_request_funcs

In my python3 flask application I would like to execute a couple of recurring tasks before the first request.
In order to achieve this, I want to make use of the#app.before_first_request_funcs.
Can anyone please give me an example usage of #app.before_first_request_funcs?
Here is my sample code:
import threading
import time
from flask import Flask
app = Flask(__name__)
def activate_job():
def run_job():
while True:
print("recurring task")
time.sleep(3)
thread = threading.Thread(target=run_job())
thread.start()
def activate_job2():
def run_job2():
while True:
print("recurring task2")
time.sleep(3)
thread = threading.Thread(target=run_job2())
thread.start()
#app.after_first_request(activate_job())
#app.before_first_request(activate_job2())
#app.route('/')
def home():
return {"action": "This has done something"}
if __name__ == '__main__':
print(app.before_first_request_funcs)
app.run()
As per the documentation, you should use #app.before_first_request to do what you want.
from flask import Flask
app = Flask(__name__)
def some_func(some_arg):
print('coucou')
# #app.before_first_request(some_func)
#app.route('/')
def home():
return {"action" : "This has done something"}
if __name__ == '__main__':
print(app.before_first_request_funcs)
app.run()
You can see the behavior of the method before_first_request_funcs that is not a decorator by commenting and uncommenting the decorator before_first_request.
If it is commented, it'll print an empty list, and if you uncomment the line, it'll return a list of one element containing the function some_func object (for me, it was [<function some_func at 0x0000021393A0AD90>]).

saving data to mongodb using pymongo

I am having an issue trying to save data to MongoDB.
I first run this python program:
import pymongo
import sys
def main():
connection = pymongo.Connection("mongodb://localhost", safe = True)
db = connection.m101
people = db.people
person = {'name':'Barack Obama', 'role':'president'}
people.insert(person)
but then, when i try to retrieve the data from the mongoshell:
> use m101
switched to db m101
> db.people.find()
returns nothing! I'm not sure what is going on. Thanks for your help.
Your code is not working because main() is never called.
Adding
if __name__ == '__main__':
main()
will execute your defined main function when executed.
You are not executing your main() function so nothing was ever executed.
Simple solution
from flask import Flask
from flask_pymongo import PyMongo
import json
import datetime
import urllib, json
from flask import jsonify
from bson.json_util import dumps
#app.route("/saveBookings", methods=['POST'])
def saveBookings():
posts = mongo.db.bookings
post = {"meetingRoom_name": "kriti_jio",
"personName": "honey",
"meetingRoom_location": "kannauj",
"book_start_time": datetime.datetime.utcnow()}
post_id = posts.insert_one(post).inserted_id
return jsonify(status="done",id=dumps(post_id),action="Data saved Succesfully",error="false");

How to get the return value (like Ajax) using task queue on Google App Engine

I can use a task queue to change the database value, but how can I get the return value like Ajax using task queue?
This is my code:
from google.appengine.api.labs import taskqueue
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp.util import run_wsgi_app
import os
class Counter(db.Model):
count = db.IntegerProperty(indexed=False)
class BaseRequestHandler(webapp.RequestHandler):
def render_template(self, filename, template_values={}):
values={
}
template_values.update(values)
path = os.path.join(os.path.dirname(__file__), 'templates', filename)
self.response.out.write(template.render(path, template_values))
class CounterHandler(BaseRequestHandler):
def get(self):
self.render_template('counters.html',{'counters': Counter.all()})
def post(self):
key = self.request.get('key')
# Add the task to the default queue.
for loop in range(0,1):
a=taskqueue.add(url='/worker', params={'key': key})
#self.redirect('/')
self.response.out.write(a)
class CounterWorker(webapp.RequestHandler):
def post(self): # should run at most 1/s
key = self.request.get('key')
def txn():
counter = Counter.get_by_key_name(key)
if counter is None:
counter = Counter(key_name=key, count=1)
else:
counter.count += 1
counter.put()
db.run_in_transaction(txn)
self.response.out.write('sss')#used for get by task queue
def main():
run_wsgi_app(webapp.WSGIApplication([
('/', CounterHandler),
('/worker', CounterWorker),
]))
if __name__ == '__main__':
main()
How can I show the 'sss'?
The current Task Queue API doesn't support processing return values or sending them back to the point of origin. Your appengine process isn't long-lived enough for that programming paradigm to work.
In your example, it looks like what you want is something like this:
Create task
Return AJAX code that will poll a task-status handler
Task processes, updates datastore with a return value
Task-status url returns updated value
Alternatively, if you don't want to return the 'sss' to the client but instead need it for further processing, you'll need to split your method into multiple parts. The first part creates the task and then exits. At the end of the task's process, it adds a new task itself to call back into the second part with the return value.

Categories