In the following way I bind "hello.py" and "goodbye.py" with the corresponding classes (functions) and it works. If I go to "0.0.0.0:8080/hello.py" or "0.0.0.0:8080/goodbye.py", I see what I expect to see.
import web
urls = ('/(hello.py)', 'hello', '/(goodbye.py)', 'goodbye')
app = web.application(urls, globals())
class hello:
def GET(self, name):
if not name:
name = 'World'
return 'Hello, ' + name + '!'
class goodbye:
def GET(self, name):
if not name:
name = 'World'
return 'Goodbye, ' + name + '!'
if __name__ == "__main__":
app.run()
However, I do not understand why I need to use brackets. If I replace '/(hello.py)' by '/hello.py', it does not work. However, in the example here no brackets are used.
From the examples that I see (I don't know web.py too well) the get parameters should not be passed in as method parameters, but rather acquired via the web.input method, like so:
import web
urls = (
'/SomePageHello','SomePageHello',
'/SomePageGoodbye','SomePageGoodbye',
)
app = web.application(urls, globals())
class SomePageHello:
def GET(self):
user_data = web.input(name="no data")
return "<h1> Hello " + user_data.name + "</h1>"
class SomePageGoodbye:
def GET(self):
user_data = web.input(name="no data")
return "<h1> Goodbye " + user_data.name + "</h1>"
if __name__ == "__main__":
app.run()
The url should be something like:
http://127.0.0.1:8081/SomePageHello?name=dasfasd
Related
Attempting to check an in-memory list, plant_list[] against a JSON payload from an api.
If the incoming payload's dict name matches inside of plant_list the if should fire off.
Instead my script only returns null
Please point out my mistakes.
The JSON sent over the api call is:
{ "name":"swizz", "days": "7", "price": 2.00 }
Source Code
from flask import Flask, request
from flask_restful import Api, Resource
app = Flask(__name__)
api = Api(app)
#app.route('/', methods=['GET', 'POST'])
def home():
return 'Tiny'
plant_list = []
class Plant(Resource):
def get(self, name):
return {'Name':name}, 200
def post(self, name):
payload = request.get_json()
for x in range(0, len(plant_list)):
if payload['name'] == plant_list[x]['name']:
return {'message': f'''Item {payload['name']} already stored in database.'''}
else:
plant_list.append(payload)
return plant_list, 201
api.add_resource(Plant, '/plant/<string:name>')
if __name__ == '__main__':
app.run(port=9004, debug=True)
You can test for key in dict simply by: if key_name in my_dict:... So, if "price" in plant_list[x]:
You are setting plant_list as a global. If you want to use that inside a Class, you should define it inside the function in your class:
plant_list = []
class Plant(Resource):
....
def post(self, name):
global plant_list
....
Not sure why you need it as a global variable. Perhaps you want:
class Plant(Resource):
plant_list = []
....
def post(self, name):
....
Is there any way to call a webpy (GET) view (from another view) with params?
Thanks in advance.
import web
urls = (
'/(\d+)', 'index',
'/number', 'novo'
)
class index:
def GET(self, number):
return "Number: %i " % number
class number:
def GET(self):
get_index = index()
return get_index.GET(3)
app = web.application(urls, globals())
if __name__ == "__main__":
app.run()
I need to write a unit test using Mock module for a Python code with different functions:
_read_file(): opens a URL and then parse the xml using Element tree and return element tree instance.
validate_field: this filed takes arguments as field_value and order.
tree.findall function is used to get all fields_values in a list and then using the order exact value of that field is stored in a field. this file is then compared with the received argument and based on comparison either true of false is returned.
I have written unit test for above function. I have mocked urllib.urlopen and the return value of the called function, but it's giving error as:
IndexError: list index out of range
Please guide me on this.
Code below:
class test:
def __init__(self, host, service_path='/policy/test.xml'):
self.base_url = 'https://' +host + service_path
self.service_path = service_path
self.host = host
def _read_policy(self, url):
policy_xml = urllib.urlopen(url)
self.tree = ElementTree.parse(policy_xml)
return self.tree
def compare(self, arg1, arg2):
if arg1 == arg2:
return 'true'
else:
return 'false'
def validate_email(self, email, order):
index = int(order) - 1
email_list = self.tree.findall("testList/test/email")
xml_email = email_list[index].text
_resp = self.compare(xml_email, email)
return(_resp)
Test class:
class test_validate_email(unittest.TestCase):
def test_validate_email(self):
myMock = Mock( return_value = StringIO.StringIO("""<?xml version="1.0" encoding="utf-8"?><email>*#test.com</email>"""))
urllib.urlopen = myMock
print 'urllib.urlopen', urllib.urlopen()
cp = test(DEFAULT_HOST)
tree = cp._read_policy("some data")
ElementTree.dump(tree)
myMock2 = Mock(return_value = 'true')
_resp = myMock2
print 'test_resp', _resp()
resp = cp.validate_email('*#ashishtest.com','1')
print 'resp', resp
self.assertEqual(resp, 'true')
if __name__ == '__main__':
unittest.main()
Here is code, the class 'demo' defined by exec is not working when create a demo instance in _getTestObj().
FileName: test.py
class runOneIni():
def _getTestObj(self):
demo(self.tcName,secSetup,doc)
def start():
#implicit define 'demo' class by exec is not working, get error in runOneIni->_getTestObj, Error is :
# NameError: name 'demo' is not defined
a='global demo'
exec(a)
str="class demo(tInvokeMethod.tInvokeMethod): pass'
exec(str)
#Explict define demo class is working
#global demo
#class demo(tInvokeMethod.tInvokeMethod): pass
if __name__ == '__main__':
start()
(1) You have an unterminated string
(2) It is unnecessary to use exec to do this. class is itself an executable statement, which can appear anywhere any other statement can (except for a place where an expression statement is required).
You could do something like this:
class SomeBaseClass(object):
def __init__(self):
self.a = 1
self.b = 2
def make_new_class(name):
class TemplateClass(SomeBaseClass):
def __init__(self):
SomeBaseClass.__init__(self)
self.a = 3
return type(name, (TemplateClass,), {})
o1 = SomeBaseClass()
print o1.a, o1.b
NewClass = make_new_class('NewClass')
o2 = NewClass()
print o2.a, o2.b
Result:
1 2
3 2
The problem is not with defining a class via exec. The following works as intended:
exec 'class hi: pass'
Your problem is that "global" inside an exec statement has no effect outside it. According to the python documentation for exec:
the global is a directive to the parser. It applies only to code parsed at the same time as the global statement. In particular, a global statement contained in an exec statement does not affect the code block containing the exec statement, and code contained in an exec statement is unaffected by global statements in the code containing the exec statement.
Why are you doing that? (exec apart)
Why are you trying to do that with exec?
Also, doing it with exec will:
Not work.
Give different results in python-2.x and in python-3.x.
Example:
class demo:
a = 'a'
print(demo.a)
def start():
global demo
class demo: b = "b"
try:
print(demo.a)
except AttributeError:
print(demo.b)
if __name__ == '__main__':
start()
try:
print(demo.a)
except AttributeError:
print(demo.b)
That either in python-2.x and in python-3.x will give:
a
b
b
And now let's try it with exec:
class demo:
a = 'a'
print(demo.a)
def start():
exec('global demo', globals(), locals())
exec('class demo: b = "b"', globals(), locals())
try:
print(demo.a)
except AttributeError:
print(demo.b)
if __name__ == '__main__':
start()
try:
print(demo.a)
except AttributeError:
print(demo.b)
Output python2.7:
a
b
a
Output python3.2:
a
a
a
Q: How to 'dynamically create the class'?
As kindall already told you, exec is not the way to do that.
A metaclass or a class factory does that, but are you sure you actually need that?
I might be a little late to the party but I came up with something that seems to work okay. It will even correct type because of the setting property.
I'm sure this is all horribly unpythonic, but I think it's kinda fun.
def generateClass(propertyNames,propertyTypes):
string = 'class generatedClass(object):\n def __init__(self):\n'
for pN in propertyNames:
string += ' self._m' + pN + ' = None\n'
string += ' \n \n'
i = 0
for pN in propertyNames:
string += ' #property\n' \
' def ' + pN + '(self):\n' \
' return self._m' + pN + '\n' \
' #' + pN + '.setter' +'\n' \
' def ' + pN + '(self,a'+ pN + '):\n' \
' if a' + pN + ':\n'\
' self._m'+ pN + ' = ' + propertyTypes[i] + '(a' + pN + ')\n'\
' \n'
i += 1
exec(string)
return generatedClass()
if __name__ == '__main__':
c = generateClass(['SomePropertyName'],['str'])
print c.__dict__
setattr(c,'SomePropertyName','some string')
print c.__dict__
You need to add the global demoin the same exec string.
here the code with the result
class RunOneIni:
def _getTestObj(self):
self.tcName = 'tn'
print(demo(self.tcName, 'secSetup', 'doc').__class__.__name__)
def start():
t = 'class tInvokeMethod:\n\tclass tInvokeMethod:\n\t\tpass'
exec(t)
d = 'global demo\nclass demo(tInvokeMethod.tInvokeMethod):\n\tdef __init__(self, *args): pass'
exec(d)
demo()
if __name__ == '__main__':
start()
RunOneIni()._getTestObj()
I have a class that doesn't extend webapp.RequestHandler, and I can't use self.response.out.write(), I get:
AttributeError: Fetcher instance has no attribute 'response'
If I extend webapp.RequestHandler (I thought it would work), I get:
AttributeError: 'Fetcher' object has no attribute 'response'
How can I use that method properly? Sometimes print doesn't work either; I just get a blank screen.
EDIT:
app.yaml:
application: fbapp-lotsofquotes
version: 1
runtime: python
api_version: 1
handlers:
- url: .*
script: main.py
source (the problematic line is marked with #<- HERE):
import random
import os
from google.appengine.api import users, memcache
from google.appengine.ext import webapp, db
from google.appengine.ext.webapp import util, template
from google.appengine.ext.webapp.util import run_wsgi_app
import facebook
class Quote(db.Model):
author = db.StringProperty()
string = db.StringProperty()
categories = db.StringListProperty()
#rating = db.RatingProperty()
class Fetcher(webapp.RequestHandler):
'''
Memcache keys: all_quotes
'''
def is_cached(self, key):
self.fetched = memcache.get(key)
if self.fetched:
print 'ok'#return True
else:
print 'not ok'#return False
#TODO: Use filters!
def fetch_quotes(self):
quotes = memcache.get('all_quotes')
if not quotes:
#Fetch and cache it, since it's not in the memcache.
quotes = Quote.all()
memcache.set('all_quotes',quotes,3600)
return quotes
def fetch_quote_by_id(self, id):
self.response.out.write(id) #<---------- HERE
class MainHandler(webapp.RequestHandler):
def get(self):
quotes = Fetcher().fetch_quotes()
template_data = {'quotes':quotes}
template_path = 'many.html'
self.response.out.write(template.render(template_path, template_data))
class ViewQuoteHandler(webapp.RequestHandler):
def get(self, obj):
self.response.out.write('viewing quote<br/>\n')
if obj == 'all':
quotes = Fetcher().fetch_quotes()
self.render('view_many.html',quotes=quotes)
else:
quotes = Fetcher().fetch_quote_by_id(obj)
'''for quote in quotes:
print quote.author
print quote.'''
def render(self, type, **kwargs):
if type == 'single':
template_values = {'quote':kwargs['quote']}
template_path = 'single_quote.html'
elif type == 'many':
print 'many'
self.response.out.write(template.render(template_path, template_values))
'''
CREATORS
'''
class NewQuoteHandler(webapp.RequestHandler):
def get(self, action):
if action == 'compose':
self.composer()
elif action == 'do':
print 'hi'
def composer(self):
template_path = 'quote_composer.html'
template_values = ''
self.response.out.write(template.render(template_path,template_values))
def post(self, action):
author = self.request.get('quote_author')
string = self.request.get('quote_string')
print author, string
if not author or not string:
print 'REDIRECT'
quote = Quote()
quote.author = author
quote.string = string
quote.categories = []
quote.put()
def main():
application = webapp.WSGIApplication([('/', MainHandler),
(r'/view/quote/(.*)',ViewQuoteHandler),
(r'/new/quote/(.*)',NewQuoteHandler) ],
debug=True)
util.run_wsgi_app(application)
if __name__ == '__main__':
main()
You're not routing to Fetcher when you initialize a WSGIApplication. Rather, you create an instance manually in other handlers. Thus, App Engine will not initialize your request and response properties. You can manually do so in from the handlers you route to, such as MainHandler and ViewQuoteHandler. E.g.:
fetcher = Fetcher()
fetcher.initialize(self.request, self.response)
quotes = fetcher.fetch_quotes()
Note that fetcher really doesn't have to be a RequestHandler. It could be a separate class or function. Once you have request and response objects, you can pass them around as you choose.