2 way to call a resource in Flask-Restful? - python

I'm learning and using Python, Flask and Flask-Restful for traineeship and I got a question :
Right now I've something like this
class CheckTXT(Resource):
def get(self):
import dns.resolver
dmn = request.args.get('dmn')
answers = dns.resolver.query(dmn, 'TXT')
c = []
for rdata in answers:
for txt_string in rdata.strings:
c.append(txt_info(dmn, txt_string))
end = time.time()
tm = end - start
return lookup("TXT", dmn, c, tm)
and
api.add_resource(CheckTXT, '/lookup/txt')
I'd like to call it by 2 way :
lookup/txt?dmn=stackoverflow.com
/lookup/txt/stackoverflow.com
The first one is working but I don't know how to do the second or even if it's possible.
Someone can help me ?
Thanks for your attention and your patience ! You're helping a young padawan ahah

Yes you can use below as endpoint and possible with flask resful
/lookup/txt/stackoverflow.com
for that you need to add resources like
api.add_resource(CheckTXT, '/lookup/txt/<string:name>') and you can access that field in your implementation like below
class CheckTXT(Resource):
def get(self,name):
print name

Related

about python recursive import in python3 when using type annotation

After spending another three hours, I thought I may got the solution.forward-references
if there isn't any better way to do this, I'll close this question later and post that solution
I'm doing reverse engineering on a program (and try to implement it using Python).
I got this problem
for example
I have a class in ComponentOfCar.py, the code is as follows
__all__ = ("ComponentOfCar");
import Car;
#...#imports other needed packages
class ComponentOfCar(object):
def __init__(self, owner:Car.Car):
self.owner = owner;
self.type = "Default";
#....#create other attribute
Another class like this(Car.py):
__all__ = ("Car");
import ComponentOfCar;
#...#imports other needed packages
class Car(object):
__slots__ = ("m_lstComponents",....);
def __init__(self, data:FlatBuffersBinaryData):
self.m_lstComponents = list();
self.LoadFromData(data);
#....#create other attribute
def InstallComponen(self, component:ComponentOfCar.ComponentOfCar)->bool:
self.m_lstComponents.append(component);
return True;
But after doing so I came across this problem:
Traceback (most recent call last):
File "Y:\Car.py", line 2, in <module>
import ComponentOfCar;
File "Y:\ComponentOfCar.py", line 2, in <module>
import Car;
File "Y:\Car.py", line 4, in <module>
class Car(object):
File "Y:\Car.py", line 10, in Car
def InstallComponen(self, component:ComponentOfCar.ComponentOfCar)->bool:
AttributeError: module 'ComponentOfCar' has no attribute 'ComponentOfCar'
The original program is written in a compiled language. Inside that the class inheritance is very complicated, and it has hundreds classes, Which makes me headache.
I want to make this process a bit clearer by using type annotations and seperate each class into individual files. But this would have to use recursive import.
After googleing for half day, I havn't find some solution, so I come here to seek help. Is Python cannot do this like compiled language, or I just make some mistake? I'm confused. How can I fix it.
Sorry about my broken English. And thanks for your time. :)
to be detailed
Here is the structure of the decompiled class declaration like this(it's c#, the whole file is about a hundred thousands of lines):
// Namespace: GameNamespace
public class Car
{
// Fields
protected List`1<ComponentOfCar> m_lstComponents;
public int ObjectID;
// Methods
public void .ctor(Data data);
public void AddComponent(ComponentOfCar c);
}
// Namespace: GameNamespace
public abstract class ComponentOfCar
{
// Fields
protected Car m_owner;
// Properties
public Car Owner { get; }
// Methods
public Car get_Owner();
public void .ctor(Car owner);
}
Or my question is how to use python to implement this clearly.
Yes, in my thought the way to do this showed above, I know that it's wrong, but I have no idea about how to make it right.
I shouldn't separate them? Or I can have them written in another way (to avoid rescursive import and) to do the same thing as in c#?
Please tell me a way to solve this, thank you very much.
After spending another three hours, I thought I may got the solution
forward-references , I'm checking this. And if there isn't any better way to do this, I'll close this question later and post that solution, it may fixes my code.
Hope this would help,
component.py
class Component:
def __init__(self, owner, data):
self.owner = owner
self.name = data['name']
car.py
from component import Component
class Car:
def __init__(self, data):
self.components = []
self.type = data['type']
self.color = data['color']
def add_car_components(self, data):
self.components.append(Component(self, data));
c = Car({'type': 'bus', 'color': 'red'})
c.add_car_components({'name': 'frontdoor'})
c.add_car_components({'name': 'reardoor'})
for component in c.components:
print(component.owner.type, component.owner.color, component.name)
Result:
->python car.py
bus red frontdoor
bus red reardoor
After some test, I finally got my solution. Perhaps it isn't the best way to do this (fix recursive import) but it fit my original thought.
which is said in this link.
After some thinking, I thought this might be called forward-references, ad according to that doc link. I rewrite this two class as bellow:
ComponentOfCar.py:
__all__ = ("ComponentOfCar");
import Car;
class ComponentOfCar(object):
__slots__=("owner","name");
def __init__(self, owner:'Car.Car',prop:dict={"name":"NoName"}):
self.owner = owner;
self.name = prop["name"];
if __name__=="__main__":
c=Car.Car({"type":"bus","color":"red"});
door1=ComponentOfCar(c,{"name":"frontdoor"});
door2=ComponentOfCar(c,{"name":"reardoor"});
c.InstallComponent(door1);
c.InstallComponent(door2);
print("We got the car",c);
for component in c.m_lstComponents:
print(component.name,component.owner);
comp1=c.m_lstComponents[0];#now we look at the first component
print("the component %s was installed on a %s %s"%(str(comp1),
comp1.owner.color,comp1.owner.type));
Car.py:
__all__ = ("Car");
import ComponentOfCar;
class Car(object):
__slots__ = ("m_lstComponents","type","color");
def __init__(self, data:dict):
self.m_lstComponents = list();
self.type=data["type"];
self.color=data["color"];
def InstallComponent(self, component:'ComponentOfCar.ComponentOfCar')->bool:
self.m_lstComponents.append(component);
return True;
if __name__=="__main__":
c=Car({"type":"bus","color":"red"});
door1=ComponentOfCar.ComponentOfCar(c,{"name":"frontdoor"});
door2=ComponentOfCar.ComponentOfCar(c,{"name":"reardoor"});
c.InstallComponent(door1);
c.InstallComponent(door2);
print("We got the car",c);
for component in c.m_lstComponents:
print(component.name,component.owner);
comp1=c.m_lstComponents[0];#now we look at the first component
print("the component %s was installed on a %s %s"%(str(comp1),comp1.owner.color,comp1.owner.type));
And now, I can run this code correctly, and I got output like:
We got the car <__main__.Car object at 0x0000015904C6AAC8>
frontdoor <__main__.Car object at 0x0000015904C6AAC8>
reardoor <__main__.Car object at 0x0000015904C6AAC8>
the component <ComponentOfCar.ComponentOfCar object at 0x0000015904C647F0> was installed on a red bus
Now I can write python code strictly according to the assemble code. I can go on my work.
And if there is some better way to satisfy my need, please correct me.
Thanks for everyone. :)

Dynamic python/flask route function naming

first off, a disclaimer: I'm not well versed in python or flask, so bear with me.
I'm trying to put together a minimal API using flask, i was planning to dynamically generate routes and their associated procs from the contents of a subdirectory.
The code looks something like this:
from flask import Flask
import os
app = Flask(__name__)
configs = os.getcwd() + "/configs"
for i in os.listdir(configs):
if i.endswith(".json"):
call = "/" + os.path.splitext(i)[0]
#app.route(call, methods=['POST'])
def call():
return jsonify({"status": call + "Success"}), 200
The plan being to iterate over a bunch of config files and use their naes to define the routes. Now, this works for a single config file, but wont work for multiple files as I end up trying to overwrite the function call that is used by each route.
I can factor out most of the code to a separate function as long as i can pass in the call name. However it seems that however i go about this i need to dynamically name the function generated and mapped to the route.
So, my question is: how can use the contents of a variable, such as 'call' to be the function name?
i.e. something like
call = "getinfo"
def call(): # Effectively being evaled as def getinfo():
Everything i've tried hasn't worked, and i'm not confident enough in my python syntax to know if it's because i'm just doing something silly.
Alternatively is there another way to do what i'm trying to achieve?
Thanks for all and any feedback!
Thanks for the help. I've moved to one route and one handler and building up the file list, and handling of the request paths, etc separately.
This is a sanitized version of the model i now have:
from flask import Flask
import os
calls = []
cfgs = {}
app = Flask(__name__)
configs = os.getcwd() + "/configs"
for i in os.listdir(configs):
if i.endswith(".json"):
cfgs[call] = os.path.splitext(i)[0]
calls.extend([call])
#app.route('/<call>', methods=['POST'])
def do(call):
if call not in calls:
abort(400, "invalid call")
# Do stuff
return jsonify({"status": call + "Success"}), 200
if __name__ == '__main__':
app.run(debug=True)
So, thanks to the above comments this is doing what i'm after. Still curious to know if there is any way to use variables in function names?

Making a pythonic decision on developing a web scraper module

This is a fairly high level question.
I have developed many different web scrapers that work in different websites.
I have many different versions of the functions named getName() and getAddress().
Is it pythonic/not terrible coding practice to do this in the function of a module? If this is bad to do, could someone give me a high level tip on how to manage this kind of library-of-scrapers?
def universalNameAdressGrab(url):
page = pullPage(url)
if 'Tucson.com' in url:
import tucsonScraper
name = getName(page) #this is the getName for Tucson
address = getAddress(page)
elif 'NewYork.com' in url:
import newyorkScraper
name = getName(page) #this is the getName for NewYork
address = getAddress(page)
return {'name':name, 'address':address}
It is probably more pythonic to import everything at the top of the file. After that you can reference the functions by module and remove a lot of duplicated code. You may run into issues with URL capitalization, so I would standardize that as well. You could use urlparse for that. I would consider something like the following more pythonic:
import tucsonScraper
import newyorkScraper
def universalNameAdressGrab(url):
page = pullPage(url)
scraper = None
if 'Tucson.com' in url:
scraper = tucsonScraper
elif 'NewYork.com' in url:
scraper = newyorkScraper
else:
raise Exception("No scraper found for url")
return {'name': scraper.getName(page), 'address': scraper.getAddress(page)}

GAE - How Do i edit / update the datastore in python

I have this datastore model
class Project(db.Model)
projectname = db.StringProperty()
projecturl = db.StringProperty()
class Task(db.Model)
project = db.ReferenceProperty(Project)
taskname= db.StringProperty()
taskdesc = db.StringProperty()
How do I edit the value of taskname ? say I have task1 and i want to change it to task1-project
oops sorry, Here is the formatted code:
taskkey = self.request.get("taskkey")
taskid = Task.get(taskkey)
query = db.GqlQuery("SELECt * FROM Task WHERE key =:taskid", taskid=taskid)
if query.count() > 0:
task = Task()
task.taskname = "task1-project"
task.put()
by the way, I get it now. I changed the task=Task() into task = query.get() and it worked.
Thanks for helping by the way.
Given an instance t of Task (e.g. from some get operation on the db) you can perform the alteration you want e.g. by t.taskname = t.taskname + '-project' (if what you want is to "append '-project' to whatever was there before). Eventually, you also probably need to .put t back into the store, of course (but if you make multiple changes you don't need to put it back after each and every change -- only when you're done changing it!-).
Probably the easiest way is to use the admin console. Locally it's:
http://localhost:8080/_ah/admin
and if you've uploaded it, it's the dashboard:
http://appengine.google.com/dashboard?&app_id=******
Here's a link:

App Engine - problem trying to set a Model property value

I'm pretty new to app engine, and I'm trying to set a bit of text into the app engine database for the first time.
Here's my code:
def setVenueIntroText(text):
venue_obj = db.GqlQuery("SELECT * FROM Venue").get()
venue_obj.intro_text = text # Works if I comment out
db.put(venue_obj) # These two lines
This throws some sort of exception - I can't tell what it is though because of my django 1.02 setup.
Ok, I gave the code in the answer below a go, and it worked after deleting my datastores, but I'm still not satisfied.
Here's an update:
I've modified my code to something that looks like it makes sense to me. The getVenueIntroText doesn't complain when I call it - I haven't got any items in the database btw.
When I call setVenueIntroText, it doesn't like what I'm doing for some reason - if someone knows the reason why, I'd really like to know :)
Here's my latest attempt:
def getVenueIntroText():
venue_info = ""
venue_obj = db.GqlQuery("SELECT * FROM Venue").get()
if venue_obj is not None:
venue_info = venue_obj.intro_text
return venue_info
def setVenueIntroText(text):
venue_obj = db.GqlQuery("SELECT * FROM Venue").get()
if venue_obj is None:
venue_obj = Venue(intro_text = text)
else:
venue_obj.intro_text = text
db.put(venue_obj)
I think this should work:
def setVenueIntroText(text):
query = db.GqlQuery("SELECT * FROM Venue")
for result in query:
result.intro_text = text
db.put(result)
I think the main problem was that I couldn't see the error messages - really stupid of me, I forgot to put DEBUG = True in my settings.py
It turns out I needed a multiline=True in my StringProperty
Django is catching my exceptions for me.

Categories