How to structure re-used code between modules - python

I'm pretty new to Python and, in writing an app, have ended up with a structure that's a bit of a mess. The example below should illustrate what I'm trying to do. The issue is that I can't call the login method from common.py because it is only defined in website1.py or website2.py.
Module common.py
class Browser():
def load_page():
Login.login()
Module website1.py
import common.py
class Login:
#staticmethod
def login():
#code to login to this website 1
Module website2.py
import common.py
#staticmethod
class Login:
def login():
#code to login to website 2
Any thoughts on how to restructure this would be appreciated.

First of all, why static methods? You could just do def login at the global level.
Second of all, you could pass a class reference to the Browser class. (or a module reference if you take my first suggestion)
class Browser(object):
def __init__(self, loginCls):
self.loginCls = loginCls
def login_page(self):
self.loginCls.login()

Related

Python - Define class method outside class - Can't start method name with underscore

I'm defining a class method outside of the class and in a different module, but I am unable to start the name of the function with an underscore. I was wondering why that is, and if anyone can suggest a good naming convention.
My current approach is below. My intent is that the underscores helps to remember it is intended for a class method,
######
# main.py
######
class MyClass:
method = _MyClass_fcn
######
# helper.py
######
def _MyClass_fcn():
# definition
if both your files are in the same folder. follow the below code
Helper.py
def _MyClass_fcn():
return 'HellNo'
def hello():
return 'hello'
Main.py
from helper import _MyClass_fcn
from helper import * # if you have more than one function in that file
class MyClass:
method = _MyClass_fcn()
print(method)
q = MyClass()

Import Django class from view to another file

Good afternoon everybody,
I'm fighting with my custom class defined in my Django view in order to use it inside another python file which let me to manage my Menu.
This class is pretty simple, but she uses a custom middleware too:
# main.views.py file
class MyClass:
def my_main_function(self, request):
my_queryset = myModel.objects.filter(application=request.cur_app, display=True).order_by('order')
return my_queryset
def toto(self):
list_test = self.my_main_function()
return list_test
request.cur_app corresponds to my middleware defined in middleware.py file.
I created toto() because I would like to use my_main_function inside another file called menus.py which doesn't handle request.
In this file, I have:
from .views.main import MyClass
for element in MyClass.toto():
... do something ...
But this is the issue encountered:
toto() missing 1 required positional argument: 'self'
I'm conscient there is a possibility of huge issues in my code, because I'm learning programmation at the same time. Be indulgent.

How to make Class instance in main.py available in another file?

I am having difficulty where I need to make the information available in a class that is instantiated in main.py in another file. The best way to describe what I am trying to do can be seen in the flow diagram below:
The issue as you can imagine is with circular dependency. Is there a way to create an interface between schema.py and main.py so that I can pass class information?
Thank you for your time and any help you can offer!
EDIT: Added code for reference
ws_transport.py
from autobahn.twisted.websocket import (
WebSocketServerProtocol,
WebSocketServerFactory,
)
from schema import schema
class WsProtocol(WebSocketServerProtocol):
def __init__(self):
# Code here
def onConnect(self, request):
# Code here
def onMessage(self, payload, isBinary):
# Code here
class WsProtocolFactory(WebSocketServerFactory):
def __init__(self):
super(WsProtocolFactory, self).__init__()
self.connection_subscriptions = defaultdict(set)
# Code here
def check_events_db(self):
# Code here
def check_audit_log_db(self):
# Code here
web_transport.py
import sys, os
import json
from twisted.web.resource import Resource
from twisted.web.server import Site, http
from schema import schema
class HttpResource(Resource):
isLeaf = True
def render_OPTIONS(self, request):
# Code here
def render_GET(self, request):
# Code here
def render_POST(self, request):
# Code here
class LoginResource(Resource):
isLeaf = True
def render_OPTIONS(self, request):
# Code here
def render_GET(self, request):
# Code here
def render_POST(self, request):
# Code here
class RefreshResource(Resource):
isLeaf = True
def render_OPTIONS(self, request):
# Code here
def render_GET(self, request):
# Code here
def render_POST(self, request):
# Code here
class HttpFactory(Site):
def __init__(self, resource):
# Code here
schema.py
#!/usr/bin/python
import graphene
import json
import sys, os
from main import factory
class Query(graphene.ObjectType):
# Code here
class Mutation(graphene.ObjectType):
# Code here
class Subscription(graphene.ObjectType):
# Code here
schema = graphene.Schema(query=Query, mutation=Mutation, subscription=Subscription)
main.py
import sys
from twisted.internet import reactor
from twisted.web.resource import Resource
from autobahn.twisted.resource import WebSocketResource
from ws_transport import WsProtocol, WsProtocolFactory
from web_transport import HttpResource, LoginResource, RefreshResource, HttpFactory
if __name__ == '__main__':
factory = WsProtocolFactory()
factory.protocol = WsProtocol
ws_resource = WebSocketResource(factory)
root = Resource()
root.putChild("", HttpResource())
root.putChild("login", LoginResource())
root.putChild("refresh", RefreshResource())
root.putChild(b"ws", ws_resource)
site = HttpFactory(root)
reactor.listenTCP(8000, site)
reactor.run()
Cheers,
Brian
I know this is not necessarily the answer you need. But I ran into the same problem and for me it meant that I have structured the project wrong. Meaning main.py or schema.py do things they are not meant to do. Of course you made the project so you get to decide what does what but what I mean is that maybe you should abstract even more. Since I do not quite understand what you want to do with the code since I do not know the libraries.
A simple hacky sort of thing is to just create another file called maybe run.py that then imports both files and dependency-injects main into schema or the other way around.
Another not-so-nice solution is to create an init() function that then imports the other file after the rest has been initialized and therefore insures that the import is only executed once.
But what I did was to check conceptually why main needed to import (in your case) schema and then ask myself is this really what main.py is supposed to do. If e.g. your main needs to provide templates to all other modules then why not create a templates.py or modules.py? Or what in my case was better is to create a bus system. This could allow modules to share only the data needed when needed and exposes a general api. But of course this would only make sense if you only share information.
In conclusion: Usually when the application is well designed you never run into circular imports. When you do it is a sign that you should rethink about how you structure your program.
For Python functions you could do something like this.
def functionInSchema(objectParameter):
# Add in code
This will give you access to the object from the main.py file.
To access attributes/methods use the parameter name, a dot and the attribute/function name.
def functionInSchema(objectParameter):
attribute = objectParameter.attribute
objectParameter.method()
Then in main.py you pass the Class instance (Object) as a parameter.
objectInMain = Class(param1, param2)
functionInSchema(objectInMain)
If you need access to the class in schema.py you can use the following import.
from main.py import ClassName
I hope this helped you! Good luck!

Calling a class method from another class causes metaclass conflict

I have a Python web app and I want to define a general class or function for processing web pages and call it from a more specific class for specific page instances.
Error:
metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
I have checked all the StackOverflow questions & answers about that error message and did not understand the explanations given (and I found an article about metaclasses that I didn't understand - OOP is not really my thing). I also looked at all the StackOverflow questions & answers about calling a class method from another class (and didn't understand them either).
Code:
import webapp2
from datetime import datetime, timedelta
from google.appengine.ext import ndb
from google.appengine.api import users
import admin_templates
import authenticate
class myPage(webapp2.RequestHandler):
def get(pageInstance):
pageInstance.outputHtml()
def outputHtml(pageInstance,pageTitle,pageContent):
adminLink = authenticate.get_adminlink()
authMessage = authenticate.get_authmessage()
adminNav = authenticate.get_adminnav()
pageInstance.response.headers['Content-Type'] = 'text/html'
html = admin_templates.base
html = html.replace('#title#', pageTitle)
html = html.replace('#authmessage#', authMessage)
html = html.replace('#adminlink#', adminLink)
html = html.replace('#adminnav#', adminNav)
html = html.replace('#content#', pageContent)
pageInstance.response.out.write(html)
pageInstance.response.out.write(admin_templates.footer)
class AuditorsPage(webapp2.RequestHandler, myPage.outputHtml):
def get(self):
self.output_auditors()
def output_auditors(self):
self.outputHtml(admin_templates.auditors_title, admin_templates.auditors_content)
How do I call the outputHtml method in the myPage class from the AuditorsPage class without getting a metaclass error?
The error comes from the fact that you are subclassing your class from a method in the general class, which can't be done. Actually, your code is wrong, and there are at least two ways you can fix it:
1) Inherit from myPage instead: in this case, it won't work and will bring a MRO error because your methods are not part of any instance of the class, as they are not linked to the object using self as the first parameter.
This is the fix for your code in this case:
from google.appengine.ext import ndb
from google.appengine.api import users
import admin_templates
import authenticate
class myPage(webapp2.RequestHandler):
def get(self, pageInstance):
pageInstance.outputHtml()
def outputHtml(self, pageInstance,pageTitle,pageContent):
adminLink = authenticate.get_adminlink()
authMessage = authenticate.get_authmessage()
adminNav = authenticate.get_adminnav()
pageInstance.response.headers['Content-Type'] = 'text/html'
html = admin_templates.base
html = html.replace('#title#', pageTitle)
html = html.replace('#authmessage#', authMessage)
html = html.replace('#adminlink#', adminLink)
html = html.replace('#adminnav#', adminNav)
html = html.replace('#content#', pageContent)
pageInstance.response.out.write(html)
pageInstance.response.out.write(admin_templates.footer)
class AuditorsPage(myPage):
def get(self):
self.output_auditors()
2) Just get the two methods in the myPage class as normal methods with no class, and then call them directly from your class. Actually, you just need to create outputHtml() method, and then call it directly (without self.) from the method in your RequestHandler subclass.
Try this:
myPage.outputHtml()
instead of:
self.outputHtml()
Class AuditorsPage could inherit from myPage
import webapp2
from datetime import datetime, timedelta
from google.appengine.ext import ndb
from google.appengine.api import users
import admin_templates
import authenticate
class myPage(webapp2.RequestHandler):
def get(pageInstance):
pageInstance.outputHtml()
def outputHtml(pageInstance,pageTitle,pageContent):
adminLink = authenticate.get_adminlink()
authMessage = authenticate.get_authmessage()
adminNav = authenticate.get_adminnav()
pageInstance.response.headers['Content-Type'] = 'text/html'
html = admin_templates.base
html = html.replace('#title#', pageTitle)
html = html.replace('#authmessage#', authMessage)
html = html.replace('#adminlink#', adminLink)
html = html.replace('#adminnav#', adminNav)
html = html.replace('#content#', pageContent)
pageInstance.response.out.write(html)
pageInstance.response.out.write(admin_templates.footer)
class AuditorsPage(myPage):
def get(self):
self.output_auditors()
Then you can instanciate AuditorsPage() and call directly outputHtml
foo = AuditorsPage()
foo.outputHtml(admin_templates.auditors_title, admin_templates.auditors_content)
Ok so you are not calling super for the AuditorsPage:
class myPage():
def __init__(self):
pass
def outputHtml(self):
print("outputHTML")
class AuditorsPage(myPage):
def __init__(self):
super().__init__()
def output(self):
print("AuditorsPage")
I am using a very stripped down version of what you have to explain what is going on. As you can see, we have your myClass class. When creating an object from AuditorsPage, we are now able to access the method outputHTML as expected. Hope this helps.
Base on your question, I guess you want to inherit methods from myPage. If that is the case, instead of:
class AuditorsPage(webapp2.RequestHandler, myPage.outputHtml):
Try:
class AuditorsPage(webapp2.RequestHandler, myPage):

Flask: using app as an attribute and accessing decorators

using the python flask module, i would like to have the
app = flask.Flask(__name__)
as a attribute of a class:
class Handler(object):
def __init__(self):
self.datastores = {}
self.websocket_queue = gevent.queue.JoinableQueue()
self.app = flask.Flask(__name__)
the problem is how to access decorators then?
#self.app.route('/socket.io/<path:remaining>')
def socketio(self, remaining):
That generates the error NameError: name 'self' is not defined
Thanks
You could try to use Flask-Classy as it provides an easy way to use classes with Python-Flask.
It depends - if you are adding handlers inside of a method of the Handler class it should work without issue:
def add_routes(self):
#self.app.route("/some/route")
def some_route():
return "At some route"
If you are attempting to add routes outside of Handler you will need to use a reference to your Handler instance:
handler = Handler()
#handler.app.route("/some/route")
def some_route():
return "At some route"

Categories