I just started studying, and in the courses we parsed the code,
but I still could understand it
can someone explain how this whole code work
This code is correct, i just want to know how it's work
The object-oriented paradigm has several principles:
Data is structured in the form of objects, each of which has a certain type, that is, belongs to a class.
Classes are the result of formalizing the problem being solved, highlighting its main aspects.
Inside the object, the logic for working with information related to it is encapsulated.
Objects in the program interact with each other, exchange requests and responses.
Moreover, objects of the same type respond in a similar way to the same requests.
Objects can be organized into more complex structures, for example, include other objects, or inherit from one or more objects.
def search_object(func):
def wrapper(*args, **kwargs):
for object_ in args[0].objects:
if object_.get("id") == args[1]:
return func(*args, object_=object_, **kwargs)
return {"status": 404, "msg": "Not found"}
return wrapper
class CRUD:
def __init__(self):
self.objects = []
self.id = 0
def create(self, **kwargs):
self.id +=1
object_ = dict(id=self.id, **kwargs)
self.objects.append(object_)
return {"status": 201, "msg": "successfully created"}
#search_object
def retrieve(self, id, **kwargs):
return kwargs["object_"]
#search_object
def delete(self, id, **kwargs):
self.objects.pop(self.objects.index(kwargs["object_"]))
return {"status": 200, "msg": "Successfully deleted"}
#search_object
def update(self, id, **kwargs):
object_ = kwargs.pop("object_")
object_.update(**kwargs)
print(id, kwargs)
return {"status": 200, "msg": "Successfully updated"}
obj1 = CRUD()
obj1.create(name="hello", last_name="world")
obj1.create(name="tratata", last_name="vatafa")
obj1.create(name="blatata", last_name="pajata")
# print("Before object removing: ", obj1.objects)
# print("Retrieved: ", obj1.retrieve(2))
# print("Deleted: ", obj1.delete(2))
# print("After object removing: ", obj1.objects)
obj1.update(1, name="Petya", last_name="Ivanov")
print(obj1.objects)
Related
#pytest.fixture(scope="session")
def create_user_access_token():
""" Used to test: refresh and revoke endpoints"""
response_data = oauth_requests.create_user_access_token()
return response_data["token"]
#pytest.fixture(scope="session")
def create_client_access_token():
""" Used to test: refresh and revoke endpoints"""
response_data = oauth_requests.create_client_access_token()
return response_data["token"]
#pytest.mark.parameterize('token', [create_client_access_token, create_user_access_token]
def test(token):
return_data = check(token)
assert return_data.status_code == 200
I understand it's not possible to do the above but how can I replicate this feature? The tests I am writing are identical for both tokens.
the fixtures are functions and request the API to create said token.
#mrBeanBremen Already started refactoring my code with the singleton pattern :). am leaving the function calls separate for flexibility. Thanks!
class Tokens:
__instance = None
def __new__(cls, user_token, client_token):
if cls.__instance is None:
cls.__instance = object.__new__(cls)
cls.__instance.user_token = user_token
cls.__instance.client_token = client_token
return cls.__instance
I am using the cms Plone to build a form that contains two other schemas.
With the Group Forms, I have been able to include both of the fields of the two schemas. However, they lose all of their properties such as hidden or when I use datagridfield to build the table. What I want to be able to do is have both of these forms with their fields and on a save be able to save them in the object which the link was clicked as parent -> object 1 [top of the form] -> object 2 [bottom of the form]
Here is my python code:
class QuestionPart(group.Group):
label = u'Question Part'
fields = field.Fields(IQuestionPart)
template = ViewPageTemplateFile('questionpart_templates/view.pt')
class Question(group.Group):
label = u'Question'
fields = field.Fields(IQuestion)
template = ViewPageTemplateFile('question_templates/view.pt')
class QuestionSinglePart(group.GroupForm, form.AddForm):
grok.name('register')
grok.require('zope2.View')
grok.context(ISiteRoot)
label = u"Question with Single Part"
ignoreContext = True
enable_form_tabbing = False
groups = (Question,QuestionPart)
def update(self):
super(QuestionSinglePart, self).update()
This code displays both the fields of IQuestion, IQuestionPart without the regard to things like: form.mode(contype='hidden') or DataGridField widget.
I found a way that displays the correct form with field hints.
class QuestionSinglePart(AutoExtensibleForm, form.AddForm):
grok.require('zope2.View')
grok.context(ISiteRoot)
label = u"Question"
schema = IQuestion
additionalSchemata = (IQuestionPart,)
I feel I am still a long way off. I have talked to some people. I am now trying to use a separate form and view.
So far, I am at this point with my code:
class QuestionSinglePartForm(AutoExtensibleForm, form.Form):
ignoreContext = True
autoGroups = True
template = ViewPageTemplateFile('questionsinglepart_templates/questionsinglepartform.pt')
#property
def additionalSchemata(self):
return self._additionalSchemata
def __init__(self, context, request, schema, additional=()):
self.context = context
self.request = request
if not IInterface.providedBy(schema):
raise ValueError('Schema is not interface object')
self._schema = schema
if not all(IInterface.providedBy(s) for s in additional):
raise ValueError('Additional schema is not interface')
self._additionalSchemata = additional
class QuestionSinglePartView(object):
schema = IQuestion
additional = (IQuestionPart,)
def __init__(self, context, request):
self.context = context
self.request = request
self.form = QuestionSinglePartForm(context, request, self.schema, self.additional)
def magic(self, data, errors):
pass
"""
question = Question()
question.number = data['number']
question.questionContent = data['questionContent']
questionPart = QuestionPart()
questionPart.typeOfQuestion = data['IQuestionPart.typeOfQuestion']
questionPart.explanation = data['IQuestionPart.explanation']
questionPart.fileSize = data['IQuestionPart.fileSize']
questionPart.fileType = data['IQuestionPart.fileType']
questionPart.hints = data['IQuestionPart.hints']
questionPart.table = data['IQuestionPart.table']
questionPart.contype = data['IQuestionPart.contype']
questionPart.content = data['IQuestionPart.content']
"""
def update(self, *args, **kwargs):
if self.request.get('REQUEST_METHOD') == 'POST':
data, errors = self.form.extractData()
self.magic(data, errors)
self.formdisplay = self.form.render()
def __call__(self, *args, **kwargs):
self.update(*args, **kwargs)
return self.index(*args, **kwargs)
I am struggling with the rendering of the form and that the QuestionSinglePart object does not have an index attribute.
After a couple of hours of working with some plone devs, we have figured out what was going on.
I had left out:
#property
def schema(self):
return self._schema
I needed to define an index in the view like so:
index = ViewPageTemplateFile('questionsinglepart_templates/questionsinglepart.pt')
I needed to add this to the views init:
alsoProvides(self.form, IWrappedForm)
In the update method for view I needed to call this before the formdisplay. I could also remove the data extraction and move that to the form.
def update(self, *args, **kwargs):
self.form.update(*args, **kwargs)
self.formdisplay = self.form.render()
I am still currently working to get the data to save into objects.
Only form classes that include the plone.autoform.base.AutoExtensibleForm mixin pay attention to schema form hints. Try using this as a mixin to your Group form class (and provide the schema attribute that this mixin looks for instead of fields):
from plone.autoform.base import AutoExtensibleForm
class QuestionPart(AutoExtensibleForm, group.Group):
label = u'Question Part'
schema = IQuestionPart
template = ViewPageTemplateFile('questionpart_templates/view.pt')
Here is my final code with the changes made above. There were issues with the index for the object. I needed to create a simple custom view. I forgot the property for schema on the form. I need to changed my update method for the view as well.
class QuestionSinglePartForm(AutoExtensibleForm, form.Form):
ignoreContext = True
autoGroups = False
#property
def schema(self):
return self._schema
#property
def additionalSchemata(self):
return self._additionalSchemata
def __init__(self, context, request, schema, additional=()):
self.context = context
self.request = request
if not IInterface.providedBy(schema):
raise ValueError('Schema is not interface object')
self._schema = schema
if not all(IInterface.providedBy(s) for s in additional):
raise ValueError('Additional schema is not interface')
self._additionalSchemata = additional
#button.buttonAndHandler(u'Save')
def handleSave(self, action):
data, errors = self.extractData()
if errors:
return False
obj = self.createAndAdd(data)
if obj is not None:
# mark only as finished if we get the new object
self._finishedAdd = True
IStatusMessage(self.request).addStatusMessage(_(u"Changes saved"), "info")
print data
#button.buttonAndHandler(u'Cancel')
def handleCancel(self, action):
print 'cancel'
class QuestionSinglePartView(object):
schema = IQuestion
additional = (IQuestionPart,)
index = ViewPageTemplateFile('questionsinglepart_templates/questionsinglepart.pt')
def __init__(self, context, request):
self.context = context
self.request = request
self.form = QuestionSinglePartForm(context, request, self.schema, self.additional)
alsoProvides(self.form, IWrappedForm)
def magic(self, data, errors):
pass
"""
question = Question()
question.number = data['number']
question.questionContent = data['questionContent']
questionPart = QuestionPart()
questionPart.typeOfQuestion = data['IQuestionPart.typeOfQuestion']
questionPart.explanation = data['IQuestionPart.explanation']
questionPart.fileSize = data['IQuestionPart.fileSize']
questionPart.fileType = data['IQuestionPart.fileType']
questionPart.hints = data['IQuestionPart.hints']
questionPart.table = data['IQuestionPart.table']
questionPart.contype = data['IQuestionPart.contype']
questionPart.content = data['IQuestionPart.content']
"""
def update(self, *args, **kwargs):
self.form.update(*args, **kwargs)
self.formdisplay = self.form.render()
def __call__(self, *args, **kwargs):
self.update(*args, **kwargs)
return self.index(*args, **kwargs)
I'm getting a value from a HTTP GET request. I'm checking whether the value is not equal to none. If it is , then return message is sent else further processing is happening.
def api_servers():
installation_name = request.args.get('installation_name', '')
if installation_name == '':
data = {"description": "Installation Name is required"}
return HttpResponse(json.dumps(data), status=400, mimetype='application/json')
data = { "arms": arms_list }
return HttpResponse(json.dumps(data), status=200, mimetype='application/json')
Now, I want to check this condition using a decorator function. This is what I'm trying.
def wrapper(func):
def inner(): # I dont know what to pass in the arguments. Installation_name?
# Maybe? But then how do I pass Installation_name
if installation_name == '':
data = {"description": "Installation Name is required"}
return HttpResponse(json.dumps(data), status=400, mimetype='application/json')
else:
return func()
return inner
How can I achieve this via decorator?
EDIT
While I was proceeding, I found that I need another decorator which checks data is None or not.It also checks whether installation_name is empty or not and then I need to "recycle" both the installation_name and data. I re-wrote your code again. But the values are being interchanged, ie data gets installation_name and vice-versa. Can you please have a look? Thanks
def with_description(fn):
def inner(*args, **kwargs):
# Precheck
installation_name = 'inst1'
if installation_name == '':
return 1
# If precheck passes
return fn(installation_name, *args, **kwargs)
return inner
def with_description1(fn):
def inner(*args, **kwargs):
# Precheck
data = 'data1'
if data == '':
return 1
# If precheck passes
return fn(data, *args, **kwargs)
return inner
#with_description
#with_description1
def api_servers1(installation_name,data):
print installation_name,data
api_servers1()
Uhm, give this a try:
import functools
def with_description(fn):
#functools.wraps(fn) # This is not strictly necessary, just pulls info (docstrings, etc) from fn and pushes into the wrapper
def wrapper(*args, **kwargs):
# Precheck
installation_name = request.args.get('installation_name', '')
if installation_name == '':
data = {"description": "Installation Name is required"}
return HttpResponse(json.dumps(data), status=400, mimetype='application/json')
# If precheck passes, call the actual function
fn(*args, **kwargs)
return wrapper
With this you win that every function decorated actually gets called only when the precheck passes.
EDIT
If as commented, you want to recycle the installation name, you just have to pass it to the function call. One possibility would be the following:
fn(installation_name, *args, **kwargs)
And of course, the decorated function has to expect that argument.
I have numerous tornado.web.RequestHandler classes that test for authorized access using id and access key secure cookies. I access mongodb asynchronously with inline callbacks using gen.Task. I am having trouble figuring out a way to factor out the repetitive code because of its asynchronicity. How can I do this?
class MyHandler(RequestHandler):
#tornado.web.asynchronous
#gen.engine
def get(self):
id = self.get_secure_cookie('id', None)
accesskey = self.get_secure_cookie('accesskey', None)
if not id or not accesskey:
self.redirect('/a_public_area')
return
try:
# convert to bson id format to access mongodb
bson.objectid.ObjectId(id)
except:
# if not valid object id
self.redirect('/a_public_area')
return
found_id, error = yield gen.Task(asyncmong_client_inst.collection.find_one,
{'_id': id, 'accesskey': accesskey}, fields={'_id': 1})
if error['error']:
raise HTTPError(500)
return
if not found_id[0]:
self.redirect('/a_public_area')
return
# real business code follows
I would like to factor the above into a function that yields perhaps an HTTP status code.
Tornado has decorator #tornado.web.authenticated. Let's use it.
class BaseHandler(RequestHandler):
def get_login_url(self):
return u"/a_public_area"
#gen.engine #Not sure about this step
def get_current_user(self):
id = self.get_secure_cookie('id', None)
accesskey = self.get_secure_cookie('accesskey', None)
if not id or not accesskey:
return False
#Are you sure need this?
try:
# convert to bson id format to access mongodb
bson.objectid.ObjectId(id)
except:
# if not valid object id
return False
#I believe that you don't need asynchronous mongo on auth query, so if it's not working - replace it with sync call
found_id, error = yield gen.Task(asyncmong_client_inst.collection.find_one,
{'_id': id, 'accesskey': accesskey}, fields={'_id': 1})
if error['error']:
raise HTTPError(500)
if not found_id[0]:
return False
return found_id
class MyHandler(BaseHandler):
#tornado.web.asynchronous
#tornado.web.authenticated
#gen.engine
def get(self):
# real business code follows
Using gen everywhere - not good practice. It can turn this world in big spaghetti. Think about it.
perhaps a decorator (not tested or anything, just some ideas)
def sanitize(fn):
def _sanitize(self, *args, **kwargs):
id = self.get_secure_cookie('id', None)
accesskey = self.get_secure_cookie('accesskey', None)
if not id or not accesskey:
self.redirect('/a_public_area')
return
try:
# convert to bson id format to access mongodb
bson.objectid.ObjectId(id)
except:
# if not valid object id
self.redirect('/a_public_area')
return
return fn(self, *args, **kwargs)
return _sanitize
dunno if you can make the check_errors work with the business logic..but maybe..
def check_errors(fn):
def _check_errors(*args, **kwargs)
found_id, error = fn(*args, **kwargs)
if error['error']:
raise HTTPError(500)
return
if not found_id[0]:
self.redirect('/a_public_area')
return
return _check_errors
then
class MyHandler(RequestHandler):
#tornado.web.asynchronous
#gen.engine
#sanitize
#check_errors #..O.o decorators
def get(self):
found_id, error = yield gen.Task(asyncmong_client_inst.collection.find_one,
{'_id': id, 'accesskey': accesskey}, fields={'_id': 1})
return found_id, error
I'd like to address this general problem with gen.Task, which is that factoring out code is either impossible or extremely clumsy.
You can only do "yield gen.Task(...)" within the get() or post() method. If you want to have get() call another function foo(), and do the work in foo(), well: You can't, unless you want to write everything as a generator and chain them together in some unwieldy way. As your project gets bigger, this is going to be a huge problem.
This is a much better alternative: https://github.com/mopub/greenlet-tornado
We used this to convert a large synchronous codebase to Tornado, with almost no changes.
I have built an application that has a lot of similar views that should be able to use the same base code. However each method has certain unique characteristics at various inflection points within the methods such that I can't figure out a way to structure this to actually reuse any code. Instead I've created a cut-and-paste methodology and tweaked each method individually. This part of the application was some of the first Python code I ever wrote and know there must be a better way to do this, but I got locked into doing it this way and "it works" so I can't see a way out.
Here's what the base view template essentially looks like:
def view_entity(request, entity_id=None):
if request.method == 'POST':
return _post_entity(request, entity_id)
else:
return _get_entity(request, entity_id)
def _get_entity(request, entity_id):
data = _process_entity(request, entity_id)
if 'redirect' in data:
return data['redirect']
else:
return _render_entity(request, data['form'])
def _post_entity(request, entity_id):
data = _process_entity(request, entity_id)
if 'redirect' in data:
return data['redirect']
elif data['form'].is_valid():
# custom post processing here
instance = data['form'].save()
return HttpResponseRedirect(reverse('entity', args=[instance.id]))
else:
return _render_entity(request, data['form'])
def _process_entity(request, entity_id):
data = {}
if entity_id != 'new': # READ/UPDATE
# sometimes there's custom code to retrieve the entity
e = entity_id and get_object_or_404(Entity.objects, pk=entity_id)
# sometimes there's custom code here that deauthorizes e
# sometimes extra values are added to data here (e.g. parent entity)
if e:
if request.method == 'POST':
data['form'] = EntityForm(request.POST, instance=e)
# sometimes there's a conditional here for CustomEntityForm
else:
data['form'] = EntityForm(instance=e)
else: # user not authorized for this entity
return {'redirect': HttpResponseRedirect(reverse('home'))}
# sometimes there's custom code here for certain entity types
else: # CREATE
if request.method == 'POST':
data['form'] = EntityForm(request.POST)
else:
data['form'] = EntityForm()
# sometimes extra key/values are added to data here
return data
I didn't even include all the possible variations, but as you can see, the _process_entity method requires a lot of individual customization based upon the type of entity being processed. This is the primary reason I can't figure out a DRY way to handle this.
Any help is appreciated, thanks!
Use class based views. You can use inheritance and other features from classes to make your views more reusable. You can also use built-in generic views for simplifying some of the basic tasks.
Check class-based views documentation. You can also read this this
So I did end up refactoring the code into a base class that all my views inherit from. I didn't end up refactoring into multiple views (yet), but instead solved the problem of having custom processing methods by inserting hooks within the processing method.
Here's the gist of the base class that inherits from DetailView:
class MyDetailView(DetailView):
context = {}
def get(self, request, *args, **kwargs):
self._process(request, *args, **kwargs)
if 'redirect' in self.context:
return HttpResponseRedirect(self.context['redirect'])
else:
return self._render(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
self._process(request, *args, **kwargs)
if 'redirect' in self.context:
return HttpResponseRedirect(self.context['redirect'])
elif self.context['form'].is_valid():
self._get_hook('_pre_save')(request, *args, **kwargs)
return self._save(request, *args, **kwargs)
else:
return self._render(request, *args, **kwargs)
def _process(self, request, *args, **kwargs):
form = getattr(app.forms, '%sForm' % self.model.__name__)
if kwargs['pk'] != 'new': # READ/UPDATE
self.object = self.get_object(request, *args, **kwargs)
self._get_hook('_auth')(request, *args, **kwargs)
if not self.object: # user not authorized for this entity
return {'redirect': reverse(
'%s_list' % self.model.__name__.lower())}
self.context['form'] = form(
data=request.POST if request.method == 'POST' else None,
instance=self.object if hasattr(self, 'object') else None)
self._get_hook('_post_process')(request, *args, **kwargs)
def _get_hook(self, hook_name):
try:
return getattr(self, '%s_hook' % hook_name)
except AttributeError, e:
def noop(*args, **kwargs):
pass
return noop
The key part to note is the _get_hook method and the places within the other methods that I use it. That way, in some complex view I can inject custom code like this:
class ComplexDetailView(MyDetailView):
def _post_process_hook(self, request, *args, **kwargs):
# here I can add stuff to self.context using
# self.model, self.object, request.POST or whatever
This keeps my custom views small since they inherit the bulk of the functionality but I can add whatever tweaks are necessary for that specific view.