I have developed two separate modules which ultimately yield an object which can be passed to cherrypy's quickstart function like chp.quickstart(the_app_object, '/', some_config). The dispatcher I use in some_config is chp.dispatch.MethodDispatcher()
Now I need to develop a module which wraps both.
As I put a reference to each of the first two apps in the third one, I get to a situation like this:
import cherrypy
#cherrypy.expose
class HandlerApp1(object):
def POST(self):
return "output_app_1"
#If mounted, HandlerApp1 may be accessed at hostname:port/path_app_1
class App1(object):
path_app_1 = HandlerApp1()
############################################################
#cherrypy.expose
class HandlerApp2(object):
def POST(self):
return "output_app_2"
#If mounted, HandlerApp2 may be accessed at hostname:port/path_app_2
class App2(object):
path_app_2 = HandlerApp2()
############################################################
#If mounted, HandlerApp1 may be accessed at hostname:port/wrapped_1/path_app_1
#and HandlerApp2 at hostname:port/wrapped_2/path_app_2
class App3(object):
wrapped_1 = App1()
wrapped_2 = App2()
What I would like to invoke both POST methods in a single call, having something like this (continues from above):
#cherrypy.expose
class HandlerApp3(object):
app_1 = App1()
app_2 = App2()
def POST(self):
return app_1.POST() + app_2.POST()
##If mounted, HandlerApp3 may be accessed at hostname:port/path_app_3
class App3(object):
path_app_3 = HandlerApp3()
However, having App3 as in the second part, the individual old applications may still be accessed at hostname:port/path_app_3/app_1 and hostname:port/path_app_3/app_2, which is what I would like to avoid.
As I understand, this is because the chosen dispatcher (chp.dispatch.MethodDispatcher()) maps url path segments to attributes of the application object along the application mount point (in this case '/'), and then invokes the attribute object method corresponding to the request method (GET, POST, etc.) if the object instance as an exposed attribute (which is set by #cherrypy.expose), which means a POST to hostname:port/path_app_3/app_1 would effectively invoke <base_app_object>.path_app_3.app_1.POST().
I was wondering if it could be possible to somehow "unexpose" exposed methods down the hierarchy.
Simply renaming attributes in the third app won't do, obviously. I am not sure whether using dictionaries or another collection would help, as it feels like some hack relying on the library not properly accessing nested collections instead of attributes (assuming this would be enough to disrupt the path matching process.
Related
I'm creating a python library that acts as library and not an app. It's a wrapper around a REST API that has complex responses and I want to abstract the parsing. The library can then be used by apps.
The REST API is around a SaaS offering so one configuration part would be the domain and another the api key. I'm aware I can create an ini file and use configparser. But that means I still need to pass the path of the config file to the library. A dict would however be preferable as that way the app can decide how to store the config. I also want to initialize the library exactly once and not have the options as method or constructor arguments (except for an initialization method).
How can I achieve that? Is it sensible to have the app require to call specific method like config(options: dict) before the library can be used?
EDIT:
Best analogy I can come up with is ORM for REST. Let's say there are Rooms, shelves and Books each backed by a set of API end points (GET, PUT etc). So I will want to create a class that wraps these calls for each item and each class like Book, Room etc needs access to the config.
An important thing is that these items are configurable in the system, eg. admins can add whatever properties to them they want and a GET call for example returns a list of properties with metadata about them (id, name, type etc). Hence the need for the wrapper.
I usually make my configuration options as constructor params where the args are optional. If the value isn't overridden then I fetch the values from environment variables. This allows developers to easily override the configuration without any complex setup.
class Api:
def __init__(self, url=None, key=None):
self.url = url or os.environ.get("MYAPP_URL", "safe default")
self.key = key or os.environ.get("MYAPP_KEY", "safe default")
If you end up getting a large amount of config items that you need to pass around, I'd follow the same pattern, but have a config class:
class ApiConfig:
def __init__(self, url=None, key=None, user=None, region=None):
self.url = url or os.environ.get("MYAPP_URL", "safe default")
self.key = key or os.environ.get("MYAPP_KEY", "safe default")
self.user = user or os.environ.get("MYAPP_USER", "safe default")
self.region = region or os.environ.get("MYAPP_REGION", "safe default")
class Api:
def __init__(self, config=None):
self.config = config or ApiConfig()
Well, here's an idea. How about writing your own config parser that uses dictionaries instead? You could write your config in JSON format and load it as a dictionary using json.loads. This way you can retrieve the configuration parameters from anywhere, including the web since JSON is web-friendly.
I am struggling to understand when it makes sense to use an instance method versus a static method. Also, I don't know if my functions are static since there is not a #staticmethod decorator. Would I be able to access the class functions when I make a call to one of the methods?
I am working on a webscraper that sends information to a database. It’s setup to run once a week. The structure of my code looks like this
import libraries...
class Get:
def build_url(url_paramater1, url_parameter2, request_date):
return url_with_parameters
def web_data(request_date, url_parameter1, url_parameter2): #no use of self
# using parameters pull the variables to look up in the database
for a in db_info:
url = build_url(a, url_parameter2, request_date)
x = requests.Session().get(url, proxies).json()
#save data to the database
return None
#same type of function for pulling the web data from the database and parsing it
if __name__ == ‘__main__’:
Get.web_data(request_date, url_parameter1, url_parameter2)
Parse.web_data(get_date, parameter) #to illustrate the second part of the scrapper
That is the basic structure. The code is functional but I don’t know if I am using the methods (functions?) correctly and potentially missing out on ways to use my code in the future. I may even be writing bad code that will cause errors down the line that are impossibly hard to debug only because I didn’t follow best practices.
After reading about when class and instance methods are used. I cannot see why I would use them. If I want the url built or the data pulled from the website I call the build_url or get_web_data function. I don’t need an instance of the function to keep track of anything separate. I cannot imagine when I would need to keep something separate either which I think is part of the problem.
The reason I think my question is different than the previous questions is: the conceptual examples to explain the differences don't seem to help me when I am sitting down and writing code. I have not run into real world problems that are solved with the different methods that show when I should even use an instance method, yet instance methods seem to be mandatory when looking at conceptual examples of code.
Thank you!
Classes can be used to represent objects, and also to group functions under a common namespace.
When a class represents an object, like a cat, anything that this object 'can do', logically, should be an instance method, such as meowing.
But when you have a group of static functions that are all related to each other or are usually used together to achieve a common goal, like build_url and web_data, you can make your code clearer and more organized by putting them under a static class, which provides a common namespace, like you did.
Therefore in my opinion the structure you chose is legitimate. It is worth considering though, that you'd find static classes more in more definitively OOP languages, like Java, while in python it is more common to use modules for namespace separation.
This code doesn't need to be a class at all. It should just be a pair of functions. You can't see why you would need an instance method because you don't have a reason to instantiate the object in the first place.
The functions you have wrote in your code are instance methods but they were written incorrectly.
An instance method must have self as first parameter
i.e def build_url(self, url_paramater1, url_parameter2, request_date):
Then you call it like that
get_inst = Get()
get_inst.build_url(url_paramater1, url_parameter2, request_date)
This self parameter is provided by python and it allow you to access all properties and functions - static or not - of your Get class.
If you don't need to access other functions or properties in your class then you add #staticmethod decorator and remove self parameter
#staticmethod
def build_url(url_paramater1, url_parameter2, request_date):
And then you can call it directly
Get.build_url(url_paramater1, url_parameter2, request_date)
or call from from class instance
get_inst = Get()
get_inst.build_url(url_paramater1, url_parameter2, request_date)
But what is the problem with your current code you might ask?
Try calling it from an instance like this and u will see the problem
get_inst = Get()
get_inst.build_url(url_paramater1, url_parameter2, request_date)
Example where creating an instance is useful:
Let's say you want to make a chat client.
You could write code like this
class Chat:
def send(server_url, message):
connection = connect(server_url)
connection.write(message)
connection.close()
def read(server_url):
connection = connect(server_url)
message = connection.read()
connection.close()
return message
But a much cleaner and better way to do it:
class Chat:
def __init__(server_url):
# Initialize connection only once when instance is created
self.connection = connect(server_url)
def __del__()
# Close connection only once when instance is deleted
self.connection.close()
def send(self, message):
self.connection.write(message)
def read(self):
return self.connection.read()
To use that last class you do
# Create new instance and pass server_url as argument
chat = Chat("http://example.com/chat")
chat.send("Hello")
chat.read()
# deleting chat causes __del__ function to be called and connection be closed
delete chat
From given example, there is no need to have Get class after all, since you are using it just like a additional namespace. You do not have any 'state' that you want to preserve, in either class or class instance.
What seems like a good thing is to have separate module and define these functions in it. This way, when importing this module, you get to have this namespace that you want.
I'm using method dispatcher in CherryPy. In the server/start.py part of the server, I need to instantiate the API classes.
To make it more modular, and not to put everything in the start.py file, I coded it like this.
So, I've a dict which has all the instantiated api classes.
services = {}
user = UserResource() #api class
foo = FooResource() #api class
services = {"user":user, "foo":foo}
class Server(object):
"""Initialise the Cherrypy app"""
#for service in services:
user = services.values()[0]
cherrypy.quickstart(Server())
That works. But, if I do services.keys()[0] = services.values()[0] it doesn't work at all. No routes.
How do I do such a thing? Where I don't have to assign it to a particular class inside the server class, but rather use the keys to add routes.
services.keys() simply returns a list. Setting the first element of that list to anything will have no effect.
I expect you want to do services[services.keys()[0]] = services.values()[0], although I can't imagine what you are trying to do with that code.
Edit
OK, I think I understand what you want to do. It seems that CherryPy relies on class-level attributes to define the routes it will serve. The docs show how to do this dynamically. In your case, you could do something like this:
class Server(object):
pass
for k, v in services:
setattr(Server, k, v)
Note that the setattr has to be done outside the class definition itself, as the Server name doesn't exist inside the class body.
If you want to have more routing flexibility, use RoutesDispatcher.
When creating a BrowserView in Plone, I know that I may optionally configure a template with ZCML like so:
<configure
xmlns:browser="http://namespaces.zope.org/browser"
>
<browser:page
…
class=".foo.FooView"
template="foo.pt"
…
/>
</configure>
Or alternatively in code:
# foo.py
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from zope.publisher.browser import BrowserPage
class FooView(BrowserPage):
"""
My View
"""
def __call__(self):
return ViewPageTemplateFile('foo.pt')(self)
Is there any difference between the two approaches? They both appear to yield the same result.
Sub-question: I know there is a BrowserView class one can import, but conventionally everyone uses BrowserPage. What if any significant differences exist between the two classes?
Note: To be fully equivalent to ZCML you should set the index variable to specify which template you are using. That way the TTW customization will work too.
# foo.py
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from zope.publisher.browser import BrowserPage
class FooView(BrowserPage):
index = ViewPageTemplateFile('foo.pt')
One other pattern you can use with a browser view is adding an update method.
class FooView(BrowserPage):
index = ViewPageTemplateFile('foo.pt')
def __call__(self):
self.update()
return self.index()
def update(self):
self.portal_catalog = ... # initialize code
But this is not the question.
So what is the difference? There is no difference. A browser view must be a callable. The ZCML directive builds this callable in a way the object has an index which must return the rendered page.
But creating the template on each call (your example) there is one difference:
you are creating a new instance of the template on each call of the browser view.
This is not the case with class variable.
One last option: You don't need a class argument in the directive
<configure xmlns:browser="http://namespaces.zope.org/browser">
<browser:page
…
template="foo.pt"
…
/>
</configure>
For more information, you should read the code of the directive, which uses SimpleViewClass where src is the template name.
In Plone, you can customize the template TTW (via portal_view_customizations) only when the template is registered explicitly (e.g. using ZCML or Grok-directives).
If you define template only in your __call__, you won't see it in portal_view_customizations.
Also, I'd guess that loading template within a method would reload it from the disk for every view instance (every request).
AFAIK, there is no difference. The ZCML directive generates a ViewClass with a ViewPageTemplateFile and renders the template on a __call__. See zope.browserpage.metaconfigure.page lines 132, 151.
That is exactly the same you do in your example: you explicitly instantiate the template in your __call__ method.
As to the subquestion: From my understanding, the significant differences are not apparent in the context of Zope2/Plone. Based on the interface (zope.publisher.interfaces.browser.IBrowserPage), the BrowserPage is the base class you want to inherit from, since it implements __call__ and browserDefault. Yet, it does not seem to matter if you use BrowserPage or BrowserView with Plone.
In the code below the User class needs to access a function get_user inside an instance of WebService class, as that contains other functions required for authentication with the web server (last.fm). Actual code is here.
class WebService:
def __init__(self, key):
self.apikey = key
def get_user(self, name):
pass # Omitted
class User:
def __init__(self, name, webservice):
self.name = name
self.ws = webservice
def fill_profile(self):
data = self.ws.GetUser(self.name)
# Omitted
The problem is that a reference needs to be held inside every ´User´. Is there another way of doing this? Or is it just me overcomplicating things, and this is how it actually works in the real world?
As requested:
As to handling things like get_top_albums and get_friends, that depends on how you want to model the system. If you don't want to cache the data locally, I'd say just call the service each time with a user ID. If you do want to cache the data locally, you could pass a User object to the method in WebService, then have the method populate the members of the User. You do have to make a design decision though to either have a WebService and a User (what would probably be best), or just a UserWebService.
You can certainly make the reference a static variable, if the web service object is the same for all users.
The syntax is:
class User:
webservice = ...
...
You will then even be able to access it from User instances, but not to assign to it that way, that would require User.webservice syntax.
You are also getting good design alternatives suggested in the comments.