I'm new to pyramid as well as the traversal concept. I have a basic object model working with traversal however the objects are location un-aware, so reading up on pyramid documentation found on this page http://docs.pylonsproject.org/projects/pyramid/en/1.0-branch/narr/resources.html#location-aware it talks about using the pyramid_traversalwrapper.
Following the instruction I added the following lines to my main:
config = Configurator(root_factory=Root)
config.registry.registerAdapter(ModelGraphTraverser, (Interface,),
ITraverser)
The rest of my traversal tree objects look like this:
class Root(object):
def __init__(self, request):
pass
def __getitem__(self, key):
if key == 'users':
return UserList()
raise KeyError
class UserList():
def __getitem__(self, key):
users = {'a':None,'b':None, 'c':None}
if key in users:
return User()
raise KeyError
class User(object):
def __init__(self):
pass
def __getitem__(self, key):
if (key == 'channels'):
return Channels()
def GET(self):
return Response("got user")
When I ran the code it does seem to use the ModelGraphTraverser when resolving urls, however what do I have to do to make my model location-aware, as in knowing the __parent__ and __name__ and such? Do I have to add wrapper classes? If so how do I go about doing it? pyramid_traversalwrapper is supposed to make managing __parent__ and __name__ effortless, but I have no idea how to take advantage of it.
pyramid_traversalwrapper automatically sets the __name__ and __parent__ attributes of the objects while traversing (you would have to do this by hand otherwise).
This means that you can use these attributes of the objects in your views. Taking your example :
#view_config(context='Channels')
def some_view(context, request):
user = context.__parent__
userlist = user.__parent__
print user.__name__ # Prints a, b or c
print userlist.__name__ # Prints 'users'
Related
I want to have abstract class Task and some derived classes like TaskA, TaskB, ...
I need static method in Task fetching all the tasks and returning list of them. But problem is that I have to fetch every task differently. I want Task to be universal so when I create new class for example TaskC it should work without changing class Task. Which design pattern should I use?
Let's say every derived Task will have decorator with its unique id, I am looking for function that would find class by id and create instance of it. How to do it in python?
There are a couple of ways you could achieve this.
the first and most simple is using the __new__ method as a factory to decide what subclass should be returned.
class Base:
UUID = "0"
def __new__(cls, *args, **kwargs):
if args == "some condition":
return A(*args, **kwargs)
elif args == "another condition":
return B(*args, **kwargs)
class A(Base):
UUID = "1"
class B(Base):
UUID = "2"
instance = Base("some", "args", "for", "the", condition=True)
in this example, if you wanted to make sure that the class is selected by uuid. you can replace the if condition to read something like
if a.UUID == "an argument you passed":
return A
but it's not really useful. since you have knowledge of the specific UUID, you might as well not bother going through the interface.
since I don't know what you want the decorator for, I can't think of a way to integrate it.
EDIT TO ADDRESS THE NOTE:
you don't need to have update it every time, if you do your expressions smartly.
let's say that the defining factor comes from a config file, that says "use class B"
for sub_classs in self.__subclasses__():
if sub_class.UUID == config.uuid:
return sub_class(*args, **kwargs) # make an instance and return it
the problem with that is that uuid is not useful to us as people. it would be easier to understand if instead we used a config.name to replace every place we have uuid in the example
I was fighting with this a lot of time and this is exactly what I wanted:
def class_id(id:int):
def func(cls):
cls.class_id = lambda : id
return cls
return func
def find_subclass_by_id(cls:type, id:int) -> type:
for t in cls.__subclasses__():
if getattr(t, "class_id")() == id:
return t
def get_class_id(obj)->int:
return getattr(type(obj), "class_id")()
class Task():
def load(self, dict:Dict) -> None:
pass
#staticmethod
def from_dict(dict:Dict) -> 'Task':
task_type = int(dict['task_type'])
t = find_subclass_by_id(Task, task_type)
obj:Task = t()
obj.load(dict)
return obj
#staticmethod
def fetch(filter: Dict):
return [Task.from_dict(doc) for doc in list_of_dicts]
#class_id(1)
class TaskA(Task):
def load(self, dict:Dict) -> None:
...
...
I'm not quite sure how to ask this question, let alone find the answer, partially because I may be completely wrong in my approach to solving this problem.
I'm writing some Python, and I have a class (Users) which is basically used to instantiate a number of objects of a particular type (User), and then provide a number of methods to help me work with those objects in a more straightforward manner. The code I have looks like this:
from defusedxml.ElementTree import parse
class Users:
def __init__(self, path):
self.path = path
self.users = []
users = parse(path).getroot()
for user in users:
u = User.user_from_xml(user)
self.users.append(u)
def __iter__(self):
self.i = 0
return self
def __next__(self):
if self.i < len(self.users):
self.i += 1
return self.users[(self.i - 1)]
else:
raise StopIteration
def get_user_by_id(self, user_id):
return next((user for user in self.users if user.id == user_id), None)
def search_attribute(self, attribute, value):
return [user for user in self.users if
getattr(user, attribute, None) != None and
value.lower() in str(getattr(user, attribute).lower())]
class User:
def __init__(self, user_id, username, email, first_name, last_name):
self.id = int(user_id)
self.username = username
self.email = email
self.first_name = first_name
self.last_name = last_name
def __repr__(self):
if self.first_name == None or self.last_name == None:
return "%s (User Id: %s)" % (self.username, self.id)
return "%s %s (%s)" % (self.first_name, self.last_name, self.username)
#staticmethod
def user_from_xml(user):
return User(
user.get("id"),
element.find("username").text,
element.find("email").text,
element.find("firstname").text,
element.find("lastname").text
)
I have a number of other objects stored in XML in a similar way - for example, Events. I can see the need to use the same methods defined in Users, with the only real difference being the type of object contained in the list created in __init__.
So the question is: what's the best way for me to make this code reuseable, while maintaining readability, etc.? Or maybe I'm on completely the wrong track.
If these class methods will truly be identical, I think the simplest method would be to just make a more generic class to replace Users that takes another class (e.g., User or Event) as an argument in its __init__ method. Your class might look like so:
class Things(object):
def __init__(self, PATH, Thing): #Thing is a class
self.PATH = PATH
self.users = []
users = parse(PATH).getroot()
for thing in things:
t = Thing.thing_from_xml(thing)
self.things.append(t)
def methods...
A more robust/scalable solution might be to use inheritance.
You could create an abstract base class that has all of your methods, and then override the base class's __init__ method within each child class. I'll draw out an example of this:
class AbstractBaseClass(object):
def __init__(self, PATH):
self.PATH = PATH
self.things = []
def methods...
class Users(AbstractBaseClass):
def __init__(self, PATH):
super(Users, self).__init__() # calls the parent __init__ method
users = parse(PATH).getroot()
for user in users:
u = User.user_from_xml(user)
self.things.append(u)
#no need to define methods, as they were already defined in parent class
#but you can override methods or add new ones if you want
Your Events class would also inherit AbstractBaseClass and thereby have all of the same methods of Users. You should read up on inheritance, it's a great tool.
EDIT TO ADDRESS YOUR COMMENT:
Properties might be a good way to get that attribute users back into to your Users class. Change things to _things to suggest that it is private, and then create a users property, like so:
class Users(AbstractBaseClass):
#property
def users(self):
return self._things
This way you can call Users.users and get Users._things.
If you really, really care about code reuse, you could even do something dynamic like this in __init__:
class AbstractBaseClass(object):
def __init__(self, PATH):
self._things = []
self.PATH = PATH
setattr(self, self.__class__.__name__.lower(), self._things)
#This creates an attribute that is the lowercase version of the
#class name and assigns self._things to it
Note: I think this is a little ugly and unnecessary. Also, since you would have two attributes that are the same thing - it might lead to your object being in an incoherent state.
That said, to me Users.users seems redundant. I'm not fully aware of the context of your problem but I think I would prefer to have my Users objects simply behave like the list users, but with extra methods (those you defined).
In AbstractBaseClass you could define __iter__ to be the __iter__ of the _things attribute.
class AbstractBaseClass(object):
def __init__(self, PATH):
self._things = []
self.PATH = PATH
def __iter__(self):
return self._things.__iter__()
#You might also want this - it lets you do list-like indexing
def __getitem__(self, i):
return self._things.__getitem__(i)
I think the above does essentially what you were doing with __iter__ and __next__ in your original code, but in a cleaner way. This way, you don't have to access _things or users directly to play with a list of your user objects; you can play with a list of users through your Users class, which, by its name, seems like the purpose of the class.
Question about objects in python. I have created the following object....
class http(object):
def __init__(self):
self._resource = None
self._response = None
#property
def resource(self):
return self._resource
#resource.setter
def resource(self, value):
self._resource = "http://127.0.0.1:8000/%s" % value
def get(self, resource=None):
self.resource = resource
self._response = requests.get(self.resource)
return self._response
Init does not need anything at this stage so I was hoping I could create the object like this....
content = http.get("users/")
but it won't let me do this, instead I have to pass use the syntax http() but pass nothing...
content = http().get("users/")
which seems silly if I don't pass anything to __init__. I'm wondering how the a Python package like requests achieves the following syntax....
requests.get('https://api.github.com/user')
without doing this...
requests().get('https://api.github.com/user')
why, what does requests package do different?
Requests defines some extra methods that create an instance of Requests.request behind the scenes. You can do the same thing for your http class.
class http(object):
def get(self, resource=None):
self.resource = resource
self._response = requests.get(self.resource)
return self._response
def get(resource=None):
temp_instance = http()
return temp_instance.get(resource)
I've got a large library of Django apps that are shared by a handful of Django projects/sites. Within each project/site there is an option to define a 'Mix In' class that will be mixed in to one of the in-library base classes (which many models sub-class from).
For this example let's say the in-library base class is PermalinkBase and the mix-in class is ProjectPermalinkBaseMixIn.
Because so many models subclass from PermalinkBase, not all the methods/properities defined in ProjectPermalinkBaseMixIn will be utilitized by all of PermalinkBase's subclasses.
I'd like to write a decorator that can be applied to methods/properties within ProjectPermalinkBaseMixIn in order to limit them from running (or at least returning None) if they are accessed from a non-approved class.
Here's how I'm doing it now:
class ProjectPermalinkBaseMixIn(object):
"""
Project-specific Mix-In Class to `apps.base.models.PermalinkBase`
"""
def is_video_in_season(self, season):
# Ensure this only runs if it is being called from the video model
if self.__class__.__name__ != 'Video':
to_return = None
else:
videos_in_season = season.videos_in_this_season.all()
if self in list(videos_in_season):
to_return = True
else:
to_return False
return to_return
Here's how I'd like to do it:
class ProjectPermalinkBaseMixIn(object):
"""
Project-specific Mix-In Class to `apps.base.models.PermalinkBase`
"""
#limit_to_model('Video')
def is_video_in_season(self, season):
videos_in_season = season.videos_in_this_season.all()
if self in list(videos_in_season):
to_return = True
else:
to_return = False
return to_return
Is this possible with decorators? This answer helped me to better understand decorators but I couldn't figure out how to modify it to solve the problem I listed above.
Are decorators the right tool for this job? If so, how would I write the limit_to_model decorator function? If not, what would be the best way to approach this problem?
was looking at your problem and I think this might be an overcomplicated way to achieve what you are trying to do. However I wrote this bit of code:
def disallow_class(*klass_names):
def function_handler(fn):
def decorated(self, *args, **kwargs):
if self.__class__.__name__ in klass_names:
print "access denied to class: %s" % self.__class__.__name__
return None
return fn(self, *args, **kwargs)
return decorated
return function_handler
class MainClass(object):
#disallow_class('DisallowedClass', 'AnotherDisallowedClass')
def my_method(self, *args, **kwargs):
print "my_method running!! %s" % self
class DisallowedClass(MainClass): pass
class AnotherDisallowedClass(MainClass): pass
class AllowedClass(MainClass): pass
if __name__ == "__main__":
x = DisallowedClass()
y = AnotherDisallowedClass()
z = AllowedClass()
x.my_method()
y.my_method()
z.my_method()
If you run this bit of code on your command line the output will be something like:
access denied to class: DisallowedClass
access denied to class: AnotherDisallowedClass
my_method running!! <__main__.AllowedClass object at 0x7f2b7105ad50>
Regards
How do I check if a property is settable or deletable in Python?
The best I've found so far is
type(obj).__dict__["prop_name"].fset is not None
This is a good case when you should subscribe to "It's Easier to Ask for Forgiveness than Permission" philosophy, and just handle the exception in case property is not settable/deletable.
try:
x.prop = 42
except AttributeError:
pass
I don't think there's any way to know up front without trying. You can't know for certain if an object has a strange __setattr__ or similar that will break the abstraction you're trying to use.
The following program tests three functions designed to find out if a class or instance property supports CRUD operations. The class or instance is the first argument to the can_* functions, and the second argument is the name of the property that should be checked. Type checking is done automatically to ensure that the functions are being used as expected. Please note that this is designed to only work with properties created with the property class from builtins module.
#! /usr/bin/env python3
def main():
for kind in Test, TestG, TestS, TestGS, TestD, TestGD, TestSD, TestGSD:
print(kind.__name__, 'Class')
print(' can_get:', can_get(kind, 'data'))
print(' can_set:', can_set(kind, 'data'))
print(' can_del:', can_del(kind, 'data'))
print()
instance = kind('Hello, world!')
print(kind.__name__, 'Instance')
print(' can_get:', can_get(instance, 'data'))
print(' can_set:', can_set(instance, 'data'))
print(' can_del:', can_del(instance, 'data'))
print()
def can_get(obj, key):
return _get_property(obj, key).fget is not None
def can_set(obj, key):
return _get_property(obj, key).fset is not None
def can_del(obj, key):
return _get_property(obj, key).fdel is not None
def _get_property(obj, key):
if not isinstance(obj, type):
obj = type(obj)
pro = vars(obj).get(key)
if not isinstance(pro, property):
raise TypeError('{.__name__}.{} is not a property'.format(obj, key))
return pro
class Test:
def __init__(self, value):
self.__data = value
def get_data(self):
return self.__data
def set_data(self, value):
self.__data = value
def del_data(self):
del self.__data
data = property()
class TestG(Test):
data = property(fget=Test.get_data)
class TestS(Test):
data = property(fset=Test.set_data)
class TestGS(Test):
data = property(fget=Test.get_data, fset=Test.set_data)
class TestD(Test):
data = property(fdel=Test.del_data)
class TestGD(Test):
data = property(fget=Test.get_data, fdel=Test.del_data)
class TestSD(Test):
data = property(fset=Test.set_data, fdel=Test.del_data)
class TestGSD(Test):
data = property(fget=Test.get_data, fset=Test.set_data, fdel=Test.del_data)
if __name__ == '__main__':
main()