Custom route predicates in Pyramid - python

I am using some custom predicates in one of my Pyramid application. Since Pyramid version 1.5, when starting the app, the following message is displayed:
my_project\__init__.py:110: DeprecationWarning: The "custom_predicates"
argument to Configurator.add_route is deprecated as of Pyramid 1.5. Use
"config.add_route_predicate" and use the registered route predicate as a
predicate argument to add_route instead. See "Adding A Third Party
View,Route, or Subscriber Predicate" in the "Hooks" chapter
of the documentation for more information.
I would like to use the new method... but I cannot find one piece of advice in how to do that...
Even the doc illustrates the old method: https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/urldispatch.html#custom-route-predicates
I tried to defined my custom predicate in my my_project\__init__.py file, using something like:
def my_predicate(info, request):
if request.something:
return True
return False
def main(global_config, **settings):
...
config.add_route_predicate('my_predicate_name', my_predicate)
config.add_route('my_route_name','/route_name/', 'my_predicate_name')
...
But that does not have any effect, I know that using 'my_predicate_name' is not the good way... I know that I am missing something, but I just cannot get what...
EDIT
If I change my code to:
config.add_route('my_route_name','/route_name/', my_predicate_name=True)
Then Pyramid throws the following error:
NameError: global name 'my_predicate_name' is not defined
It looks like the add_route_predicate does not have any effect...

This location in the documentation should explain how to implementat a custom predicate: http://docs.pylonsproject.org/projects/pyramid/en/master/narr/hooks.html#view-and-route-predicates
Here is an additional example. The response in French should only be returned when lang=fr is in the query arguments otherwise the response in English matches by default.
So / returns Hello and /?lang=fr returns bonjour.
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response
def hello_world(request):
return Response('Hello')
class LanguagePredicate():
def __init__(self, val, config):
self.val = val
def text(self):
return 'lang = %s' % (self.val,)
phash = text
def __call__(self, context, request):
return request.GET.get('lang') == self.val
def hello_world_fr(request):
return Response('bonjour')
def main():
config = Configurator()
config.add_route_predicate('lang', LanguagePredicate)
config.add_route('hello_fr', '/', lang='fr')
config.add_route('hello', '/')
config.add_view(hello_world_fr, route_name='hello_fr')
config.add_view(hello_world, route_name='hello')
app = config.make_wsgi_app()
return app
if __name__ == '__main__':
app = main()
server = make_server('0.0.0.0', 6547, app)
print ('Starting up server on http://localhost:6547')
server.serve_forever()

Related

Is there a flask function called #make_bold?? I am very confused as I am not able to find the answer anywhere

2 Days ago, I ran into a very unusual error regarding Python Flask. I was simply coding along when I ran into an error which confused me. I was doing a Python Course which showed that we can make our code easier to read if we add some decorators to the code. When I added the same decorator as the one shown in the video, I ran into an error which said
Name error: Name #make_bold is not defined
Here's the code
app = Flask(__name__)
#app.route('/')
def func():
return 'Hey'
#app.route("/bye")
#make_bold
#make_emphasis
#make_underlined
def func1():
return 'Bye'
if __name__ == "__main__":
app.run(debug=True)
Flask is a web server, meaning it can provide webpages or other info to a browser, but that doesn't mean it is designed to create webpages. In the long run you'll be much better off having Flask return a proper HTML document, but in the mean time, try including the HTML tags required for making the text bold within the actual text, since I presume that that is what the decorators (which don't appear to be built-in) are doing under the hood.
#app.route("/bye")
def func1():
return '<b><i><u>Bye</u></i></b>'
Another option could be to create the decorators yourself.
def make_bold(func):
def wrapper(*args, **kwargs):
return '<b>' + func(*args, **kwargs) + '</b>'
return wrapper
#app.route("/bye")
#make_bold
def func1():
return 'Bye'

Single instance of class from another module

I come from Java background and most of my thinking comes from there. Recently started learning Python. I have a case where I want to just create one connection to Redis and use it everywhere in the project. Here is how my structure and code looks.
module: state.domain_objects.py
class MyRedis():
global redis_instance
def __init__(self):
redis_instance = redis.Redis(host='localhost', port=6379, db=0)
print("Redus instance created", redis_instance)
#staticmethod
def get_instance():
return redis_instance
def save_to_redis(self, key, object_to_cache):
pickleObj = pickle.dumps(object_to_cache)
redis_instance.set(key, pickleObj)
def get_from_redis(self, key):
pickled_obj = redis_instance.get(key)
return pickle.loads(pickled_obj)
class ABC():
....
Now I want to use this from other modules.
module service.some_module.py
from state.domain_objects import MyRedis
from flask import Flask, request
#app.route('/chat/v1/', methods=['GET'])
def chat_service():
userid = request.args.get('id')
message_string = request.args.get('message')
message = Message(message_string, datetime.datetime.now())
r = MyRedis.get_instance()
user = r.get(userid)
if __name__ == '__main__':
global redis_instance
MyRedis()
app.run()
When I start the server, MyRedis() __init__ method gets called and the instance gets created which I have declared as global. Still when the service tries to access it when the service is called, it says NameError: name 'redis_instance' is not defined I am sure this is because I am trying to java-fy the approach but not sure how exactly to achieve it. I read about globals and my understanding of it is, it acts like single variable to the module and thus the way I have tried doing it. Please help me clear my confusion. Thanks!

flask restful: how to give multiple arguments to get methhod of any Api using flask restful?

the following is my code for get method:
def get(self, ques_no, i):
j=i
opt_dict = {}
for ques in session.query(Options.optn).filter(Options.q_no == ques_no)[j:j+2]:
opt_dict.update({i:ques.optn})
i=i+1
return jsonify(opt_dict)
api.add_resource(store_option, '/option/&&', endpoint = 'option_id')
i need to pass to arguments to my get method to access the database. but i'm not able pass to arguments. how can i do that??
any help will be appreciated..
From modifying my own code, something like this should work.
Start by defining a class like this:
class DBAccessor(Resource):
def put(self, ques_no, i):
...
return 'ok'
Now connect it like this:
app = Flask('wasp')
api = Api(app)
api.add_resource(
DBAccessor,
'/option/<ques_no>/<i>')

web.py: avoid global instances?

the last few weaks, I am playing a little bit with the Web.py framework. As my application is now getting bigger and bigger, I want to restructure the sourcecode and put code fragments in different classes. Now, I don't really know where I should create my object instances if I need them in different web.py classes. Let us assume, my sourcecode looks like:
import web
import myclass
urls = (
'/', 'index',
'/test', 'test'
)
#should i make my instance global...
my = myclass.myClass()
class test:
def __init__(self):
#...or should i make my instance local: my = myclass.myClass()
pass
def GET(self):
item = my.getItem()
return item
def POST(self):
pass
class index:
def __init__(self):
#...or should i make my instance local: my = myclass.myClass()
pass
def GET(self):
date = my.getDate()
return date
if __name__ == "__main__":
app = web.application(urls, globals())
app.run()
Now, I want to access the methods getItem() and getDate() (which belong to the instance my), if the appropriate sites in my webbrowser are called. My question is now: Should I make the instance global or is it better, if I make it local? I really don't like global instances, but I don't see any other way as to make it global. Sure, it would be possible, to create a local instance, but then, every time the page loads, a new instance would be created, right? Normally, this wouldn't be a problem, but myclass accesses a serial port, so I need to make sure, that only one instance is created.
Am I missing something or is a global instance the only possible solution to accomplish this?
After some research, I came to the conclusion, that global instances are the way to go here. However, one must be careful with global instances if they are used together with the web.py auto reload mode. In auto reload mode, a global instance is created every time a new page loads. If you want to avoid that, you have to use something like this:
import web
import serial
urls = ("/(.*)", "test"
)
web.config.debug = True
if(web.config.debug):
#in debug mode, make sure that global serial instance is only created at start up
if not hasattr(serObj, "_email"):
serObj = serial.Serial(0, 9600, parity=serial.PARITY_NONE)
web._serObj = serObj
else:
serObj = web._serObj
class test:
def GET(self):
return "Test"
def POST(self):
pass
if __name__ == "__main__":
app = web.application(urls, globals())
app.run()

twisted.web.resource.Resource with twisted.web.template.Element example

I want to use twisted.web templates together twisted.web resources.
But I just don't get, how to make them work together.
I tried using, flatten(request, MyElement(), request.write), but it ends up throwing an exception: Request.write called on a request after Request.finish was called.
Could someone provide me a very basic example how to use the two classes together?
It sounds like you forgot to return NOT_DONE_YET from your render() method, and therefore finish() was called for you immediately. Something like the following should be somewhere in Twisted itself, to help with exactly this problem:
from twisted.web.resource import Resource
from twisted.web.template import flatten
from twisted.web.server import NOT_DONE_YET
class ElementResource(Resource):
def __init__(self, element):
Resource.__init__(self)
self.element = element
def render_GET(self, request):
d = flatten(request, self.element, request.write)
def done(ignored):
request.finish()
return ignored
d.addBoth(done)
return NOT_DONE_YET

Categories

Resources