I'm trying to build a small WSGI application with Werkzeug. I have followed this tutorial it's so simple and clear. However I encounter this error:
File "/Users/username/my_app/assigment2/app.py", line 38, in __init__
self.database_engine = create_engine(db_uri)
File "/Users/Data/lib/python3.4/site-packages/sqlalchemy/engine/__init__.py", line 386, in create_engine
return strategy.create(*args, **kwargs)
File "/Users/../lib/python3.4/site-packages/sqlalchemy/engine/strategies.py", line 51, in create
dialect_cls = u.get_dialect()
AttributeError: 'function' object has no attribute 'get_dialect'
I have imported all SqlAlchemy modules
from sqlalchemy import create_engine, MetaData
from sqlalchemy.orm import create_session, scoped_session
The application fails at the init of the app.
class App(object):
def __init__(self):
local.app = self
self.database_engine = create_engine(SQLALCHEMY_DATABASE_URI )
self.jinja_env = Environment(loader=PackageLoader('app', '/templates'))
self.dispatch = SharedDataMiddleware(self.dispatch, {'/static': STATIC_PATH})
def init_database(self):
metadata.create_all(self.database_engine)
def dispatch(self, environ, start_response):
local.app = self
request = Response(environ)
local.url_= adapter = url_map.bind_to_environ(environ)
#adapter = url_map.bind_to_environ(environ)
try:
endpoint, value = adapter.match()
handler = getattr(views, endpoint)
response = handler(request, **values)
except HTTPException as e:
response = e
return ClosingIterator(response(environ, strat_response),
[session.remove, local_manager.cleanup])
def __call__(self, environ, start_response):
return self.dispatch(environ, start_response)
the databse_uri looks like this
SQLALCHEMY_DATABASE_URI = 'postgresql://user:password#localhost:5432/name_db'
STATIC_PATH = path.join(path.dirname('/static'), 'static')
Why I can't create my app like this:
def make_app():
my_app = app.App()
return my_app
I am running on Gunicorn
gunicorn -b 127.0.0.1:9000 app:make_app
New error:
TypeError: make_app() takes 0 positional arguments but 2 were given
This is wrong:
gunicorn -b 127.0.0.1:9000 app:App
What happens when there is a request:
app.App(environ, start_response)
But what you really want is:
your_app = app.App(path, db_uri)
your_app(environ, start_response)
Change gunicorn invocation to something like this:
gunicorn -b 127.0.0.1:9000 'app:App("/static/path", "postgresql://...")'
Related
This is my inside flaskapp/__init__.py for creating my Flask app, with it I can access Session inside any module in the package, by just importing Session from flaskapp/db.py:
import os
from flask import Flask
def create_app(test_config=None):
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
SECRET_KEY=b'some_secret_key',
DEBUG=True,
SQLALCHEMY_DATABASE_URI=f'sqlite:///{os.path.join(app.instance_path, "flaskapp.sqlite")}',
)
if test_config is None:
app.config.from_pyfile('config.py', silent=True)
else:
app.config.from_mapping(test_config)
try:
os.makedirs(app.instance_path)
except OSError:
pass
with app.app_context():
from flaskapp.routes import home, auth
from flaskapp.db import init_db
init_db()
return app
This is my flaskapp/db.py:
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from flask import current_app
engine = create_engine(current_app.config['SQLALCHEMY_DATABASE_URI'], echo=True)
Session = sessionmaker(bind=engine)
def init_db():
import flaskapp.models as models
models.Base.metadata.create_all(engine)
def drop_db():
import flaskapp.models as models
models.Base.metadata.drop_all(engine)
With that, I can access the database in any other module, for example, flaskapp/auth.py:
from flask import flash, session
from sqlalchemy import select
from flaskapp.db import Session
from flaskapp.models import User
def log_user(username: str, password: str) -> bool:
with Session() as db_session:
stmt1 = select(User).where(User.username == username)
query_user = db_session.execute(stmt1).first()
if not query_user:
flash('Some error message')
# Some password verifications and other things
session['username'] = query_user[0].username
flash('Successfully logged in')
return True
Until that point, I don't have any problem, the problem comes when I try to do unit testing with unittest, I can't set the test environment and I don't know how can I use the Session object defined in flaskapp/db.py for testing in a separate database. Everything I've tried until now gets me an error, this is my tests/__init__.py:
import unittest
from flaskapp import create_app
from flaskapp.db import Session
from flaskapp.models import User
class BaseTestClass(unittest.TestCase):
def setUp(self):
self.app = create_app(test_config={
'TESTING': True,
'DEBUG': True,
'APP_ENV': 'testing',
# I pass the test database URI expecting the engine to use it
'SQLALCHEMY_DATABASE_URI': 'sqlite:///testdb.sqlite',
})
self.client = self.app.test_client()
# Context
with self.app.app_context():
self.populate_db()
def tearDown(self):
pass
def populate_db(self):
with Session() as db_session:
db_session.add(User(
username='Harry',
email='harry#yahoo.es',
password = 'Harry123.'
))
db_session.commit()
When I try to use the Session object inside populate_db() I get this error:
=====================================================================
ERROR: tests.test_auth (unittest.loader._FailedTest.tests.test_auth)
----------------------------------------------------------------------
ImportError: Failed to import test module: tests.test_auth
Traceback (most recent call last):
File "/usr/local/lib/python3.11/unittest/loader.py", line 407, in _find_test_path
module = self._get_module_from_name(name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/unittest/loader.py", line 350, in _get_module_from_name
__import__(name)
File "/home/chus/usb/soft/proy/SAGC/tests/test_auth.py", line 1, in <module>
from flaskapp.db import Session
File "/home/chus/usb/soft/proy/SAGC/flaskapp/db.py", line 5, in <module>
engine = create_engine(current_app.config['SQLALCHEMY_DATABASE_URI'], echo=True)
^^^^^^^^^^^^^^^^^^
File "/home/chus/usb/soft/proy/SAGC/venv/lib/python3.11/site-packages/werkzeug/local.py", line 316, in __get__
obj = instance._get_current_object() # type: ignore[misc]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/chus/usb/soft/proy/SAGC/venv/lib/python3.11/site-packages/werkzeug/local.py", line 513, in _get_current_object
raise RuntimeError(unbound_message) from None
RuntimeError: Working outside of application context.
This typically means that you attempted to use functionality that needed
the current application. To solve this, set up an application context
with app.app_context(). See the documentation for more information.
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (errors=1)
Can someone help me out? I've tried everything to make the tests use the app context in order to populate the test database and make queries but it appears to be conflicting with it being created in create_app() or something.
Firsly, the error you posted is about tests/test_auth.py which you did not include.
However, your code is tightly coupling the flask app and the db.py module with the use of flask.current_app to obtain the engine url.
So the engine creation will only work if there is an app context, which is probably absent when you do a top level import (line 1) of from flaskapp.db import Session in tests/test_auth.py.
A solution could be creating the engine and sessionmaker (or scoped_session) with your create_app and injecting the engine or Session in your functions (look up dependency injection principle):
def init_db(engine):
models.Base.metadata.create_all(engine)
def drop_db(engine):
models.Base.metadata.drop_all(engine)
def log_user(session, username: str, password: str) -> bool:
stmt1 = select(User).where(User.username == username)
query_user = session.execute(stmt1).first()
# skipping the rest
Or look into Flask-SQLAlchemy.
I am writing unit tests in python.
I am trying the following to make it a little more efficient.
caller
class TestTrait(TestCaseCommon):
APP_NAME = 'pytest'
HEADER = {'content-type': 'application/json'}
#mock.patch('dmp_graphql.utils.common_utils.get_test_user', return_value=TestCaseCommon.mock_get_role_check_test_user(role_type=AllUserRoleEnum.SUPERADMIN))
def test_get_all_categories_super_admin(self):
print(self)
implementation
class TestCaseCommon(TestCase):
def create_app(self):
return create_app(self.APP_NAME)
def setUp(self):
db.create_all()
def tearDown(self):
db.session.remove()
db.drop_all()
def mock_get_role_check_test_user(role_type: AllUserRoleEnum, is_not_exist_user: bool = False,
account_id: int = 0):
if is_not_exist_user:
return None
if role_type == AllUserRoleEnum.SUPERADMIN:
query = db.session.query(User).filter(User.is_super_admin == True)
else:
...
pass
return user
The following error occurred.
During handling of the above exception, another exception occurred:
test_create_traits_uploader.py:7: in <module>
class TestTrait(TestCaseCommon):
test_create_traits_uploader.py:11: in TestTrait
#mock.patch('dmp_graphql.utils.common_utils.get_test_user', return_value=TestCaseCommon.mock_get_role_check_test_user(role_type=AllUserRoleEnum.SUPERADMIN))
../common.py:35: in mock_get_role_check_test_user
query = db.session.query(User).filter(User.is_super_admin == True)
/Users/lhs/.local/share/virtualenvs/hyper-dmp-v2-api-y1V5yWAL/lib/python3.8/site-packages/sqlalchemy/orm/scoping.py:163: in do
return getattr(self.registry(), name)(*args, **kwargs)
/Users/lhs/.local/share/virtualenvs/hyper-dmp-v2-api-y1V5yWAL/lib/python3.8/site-packages/sqlalchemy/util/_collections.py:1022: in __call__
return self.registry.setdefault(key, self.createfunc())
/Users/lhs/.local/share/virtualenvs/hyper-dmp-v2-api-y1V5yWAL/lib/python3.8/site-packages/sqlalchemy/orm/session.py:3309: in __call__
return self.class_(**local_kw)
/Users/lhs/.local/share/virtualenvs/hyper-dmp-v2-api-y1V5yWAL/lib/python3.8/site-packages/flask_sqlalchemy/__init__.py:136: in __init__
self.app = app = db.get_app()
/Users/lhs/.local/share/virtualenvs/hyper-dmp-v2-api-y1V5yWAL/lib/python3.8/site-packages/flask_sqlalchemy/__init__.py:987: in get_app
raise RuntimeError(
E RuntimeError: No application found. Either work inside a view function or push an application context. See http://flask-sqlalchemy.pocoo.org/contexts/.
In the above situation, is there a way to share the app with the decorator?
Or I'd like to know if it's possible to implement it in another way.
The framework used is flask and the python version is 3.8.
How can I make #celery.task available on user resources package?
I'm new to python and confused about the "circular imports error" can somebody explain how it works? and how to handle this kind of errors in flask application. This is the part where I always get stuck.
This is my project current folder structure
code
|_resources
| |_user.py
|
|_utils
| |_flask_celery.py
|
|_flask_app.py
--- SOURCE CODE ---
flask_app.py
from flask import Flask
from flask_cors import CORS
from flask_restful import Api
from util.flask_celery import make_celery
from routes.endpoint import urls
from resources.user import Users
app = Flask(__name__)
CORS(app, resources={r"/*": {"origins": "*"}})
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql:///username:StrongPassword#localhost:3306/db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['CELERY_BROKER_URL'] = 'amqp//admin:StrongPassword#localhost:5672'
app.config['CELERY_RESULT_BACKEND'] = 'db+mysql:///username:StrongPassword#localhost:3306/db'
app.config['PROPAGATE_EXCEPTIONS'] = True
api = Api(app)
celery = make_celery(app)
url = urls()
api.add_resource(Users, url.get('users'))
if __name__ == "__main__":
# sqlalchemy
from db import db
db.__init__(app)
app.run(host='0.0.0.0', debug=True, port=5000)
flask_celery.py
from celery import Celery
def make_celery(celery_app):
celery = Celery(
celery_app.import_name,
backend=celery_app.config['CELERY_RESULT_BACKEND'],
broker=celery_app.config['CELERY_BROKER_URL']
)
celery.conf.update(celery_app.config)
class ContextTask(celery.Task):
def __call__(self, *args, **kwargs):
with celery_app.app_context():
return self.run(*args, **kwargs)
celery.Task = ContextTask
return celery
user.py
from flask_restful import Resource, reqparse
from app import celery # <-- this cause the error
from util.zk_connector import zk_connect
from util.zk_error import error
class Users(Resource):
def post(self, ip, comkey):
zk = zk_connect(ip=ip, password=int(comkey))
try:
session = zk.connect()
session.disable_device()
users = session.get_users()
print(users)
session.enable_device()
session.disconnect()
return {'message': 'success'}, 200
except Exception as e:
return error(e)
#celery.task(name='user.reverse')
def reverse(string):
return string[::-1]
Error:
Traceback (most recent call last):
File ".\flask_app.py", line 6, in <module>
from resources.user import User
File "C:\Users\Gelo\Documents\Brand new clean arch pyzk\code\resources\user.py", line 2, in <module>
from flask_app import celery
File "C:\Users\Gelo\Documents\Brand new clean arch pyzk\code\flask_app.py", line 6, in <module>
from resources.user import User
ImportError: cannot import name 'User' from partially initialized module 'resources.user' (most likely due to a circular import) (C:\Users\Gelo\Documents\Brand new clean arch pyzk\code\resources\user.py)
I am fairly new to python development and have no idea about flask, I have been assigned a project that is developed using flask. After working for couple of weeks i am now able to resolve all the dependencies and project is now compiled successfully. But when I run the project using flask run and then enter the url in browser it throws "flask.cli.NoAppException". How can I run my project I have tried like this.
set FLASK_APP=init.py
set FLASK_ENV=develpment
flask run
Serving Flask app "init.py" (lazy loading)
Environment: develpment
Debug mode: on
Restarting with stat
Debugger is active!
Debugger PIN: 202-733-235
Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
here is the trackback
"FLASK_APP=myappnam:name to specify one.
Traceback (most recent call last)
File "C:\Program Files\Python38\Lib\site-packages\flask\_compat.py", line 39, in reraise
raise value
File "C:\Program Files\Python38\Lib\site-packages\flask\cli.py", line 97, in find_best_app
raise NoAppException(
flask.cli.NoAppException: Failed to find Flask application or factory in module "myappnam". Use "FLASK_APP=myappnam:name to specify one.
The debugger caught an exception in your WSGI application. You can now look at the traceback which led to the error.
To switch between the interactive traceback and the plaintext one, you can click on the "Traceback" headline. From the text traceback you can also create a paste of it. For code execution mouse-over the frame you want to debug and click on the console icon on the right side.
You can execute arbitrary Python code in the stack frames and there are some extra helpers available for introspection:
dump() shows all variables in the frame
dump(obj) dumps all that's known about the object
here is my --init--.py file
import os
import logging
import gevent
import datetime
import rollbar
from gevent.queue import Queue
from gevent.event import AsyncResult
import zmq.green as zmq
from werkzeug.contrib.fixers import ProxyFix
# Greens the postgress connector
try:
import psycogreen.gevent
psycogreen.gevent.patch_psycopg()
except ImportError:
pass
from rauth.service import OAuth2Service
from flask import Flask, Request
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from flask_login import LoginManager, current_user
from flask_assets import Environment
from flask_uploads import UploadSet, configure_uploads, IMAGES
from app.util import setup_logging
from app.exceptions import TimeoutError, BackendError
import app.exceptions
flask_app = None
# Have to use an actor pattern because we cannot allow more than one request to
# be pending at a time.
class Backend(gevent.Greenlet):
def __init__(self):
super(Backend, self).__init__()
self.inbox = Queue()
self.zmq_context = zmq.Context()
self.zmq_socket = None
self.init_socket()
def init_socket(self):
zmq_socket = self.zmq_socket
if zmq_socket is not None:
zmq_socket.close(0)
zmq_socket = self.zmq_context.socket(zmq.REQ)
zmq_socket.connect(flask_app.config["SERVER_ZMQ_URI"])
self.zmq_socket = zmq_socket
def process(self, request):
zmq_socket = self.zmq_socket
poller = zmq.Poller()
poller.register(zmq_socket, zmq.POLLIN)
zmq_socket.send_json({
"command": request["command"],
"arguments": request["arguments"]
})
sockets = dict(poller.poll(10 * 1000))
if zmq_socket not in sockets:
self.init_socket()
result = request["result"]
result.set_exception(TimeoutError("The request to the backend timed out."))
return
received = zmq_socket.recv_json()
result = request["result"]
if received["success"]:
result.set(received["result"])
else:
result.set_exception(BackendError(received["result"]))
def _run(self):
while True:
self.process(self.inbox.get())
def send(self, command, **kwargs):
result = AsyncResult()
self.inbox.put({
"command": command,
"arguments": kwargs,
"result": result
})
return result.get()
class RollbarRequest(Request):
#property
def rollbar_person(self):
if current_user.is_anonymous:
return {
"id": 0,
"username": "anonymous"
}
return {
"id": current_user.id,
"username": current_user.name,
"email": current_user.email_address
}
def create_app(*args, **kwargs):
global flask_app
global l
app_mode = os.environ.get("APP_MODE")
assert app_mode is not None, "APP_MODE environment variable must be set"
flask_app = Flask(__name__)
flask_app.request_class = RollbarRequest
flask_app.config.from_object("config.mode_{}".format(app_mode))
flask_app.config["APP_MODE"] = app_mode
setup_logging(flask_app.config["LOGGING_LEVEL"])
l = logging.getLogger(__name__)
l.info("starting in mode {}".format(app_mode))
if not flask_app.config["DEBUG"]:
rollbar.init(
flask_app.config["ROLLBAR_API_KEY"],
app_mode,
allow_logging_basic_config=False
)
flask_app.jinja_env.globals.update(
current_year=lambda: datetime.datetime.now().year
)
# Have to do this so that redirects work in proxy mode behind NGINX.
if not flask_app.debug:
flask_app.wsgi_app = ProxyFix(flask_app.wsgi_app)
flask_app.db = SQLAlchemy(flask_app)
flask_app.bcrypt = Bcrypt(flask_app)
flask_app.assets = Environment(flask_app)
flask_app.images = UploadSet("images", IMAGES)
configure_uploads(flask_app, flask_app.images)
flask_app.photos = UploadSet("photos", IMAGES)
configure_uploads(flask_app, flask_app.photos)
login_manager = LoginManager()
login_manager.login_view = "signin"
login_manager.login_message_category = "alert" # Need newer release of Flask-Login for this to work.
login_manager.init_app(flask_app)
flask_app.facebook = OAuth2Service(
name="facebook",
base_url="https://graph.facebook.com/v2.8/",
client_id=flask_app.config["FACEBOOK_CLIENT_ID"],
client_secret=flask_app.config["FACEBOOK_CLIENT_SECRET"]
)
from app import views
from app import models
from app import commands
flask_app.backend = Backend()
flask_app.backend.start()
app.exceptions.register(flask_app)
return flask_app
and this is my project structure
I am using pycharm and widows 10.
In your create_app function you probably do not want to use the global keyword for late initialisation of the app.
In the examples you provided the create_app function is never called, and so the app instance is never created. It is more common to use the create_app function as follows:
def create_app():
app = flask.Flask(__name__)
# do some setup
return app
app = create_app()
The app instance should also be called app and not flask_app. Of course you can call it whatever you want, but by default flask looks for app. To specify your own change FLASK_APP=__init__.py to FLASK_APP=__init__:flask_app
I need to use a function from a class in a different class(different file) and am having issues, not sure how to accomplish this and am struggling with trying to find the right help for what i'm looking for(i may be using the wrong terms).
Directory Structure:
--app
--static
--js
--templates
--main_page.html
--__init__.py
-- MainApp.py
--settings.py
server.py
server.py:
from gevent import monkey
from socketio.server import SocketIOServer
from app import app
monkey.patch_all()
listen_address = '0.0.0.0'
listen_port = 5000
print 'Starting Server on: http://{0}:{1}'.format(listen_address, listen_port)
SocketIOServer((listen_address, listen_port), app, resource="socket.io").serve_forever()
app > init.py
from flask import Flask
from flask import render_template
from flask import request
from socketio import socketio_manage
import settings
from celery import Celery
from redis import Redis
import subprocess
import requests
from socketio.namespace import BaseNamespace
def make_celery(app):
celery = Celery(app.import_name, broker=app.config['CELERY_BROKER_URL'])
celery.conf.update(app.config)
TaskBase = celery.Task
class ContextTask(TaskBase):
abstract = True
def __call__(self, *args, **kwargs):
with app.app_context():
return TaskBase.__call__(self, *args, **kwargs)
celery.Task = ContextTask
return celery
app = Flask(__name__)
app.debug = True
app.config.from_object(settings)
celery = make_celery(app)
r_server = Redis('localhost')
#app.route('/socket.io/<path:remaining>')
def socket(remaining):
socketio_manage(request.environ, {'/testclass': TestClass}, request)
return 'done'
#app.route('/')
def main_page():
return render_template('main_page.html')
class TestClass(BaseNamespace):
def on_submit(self, data):
#start mainapp
import MainApp
MainApp.MainApp()
#celery.task(name='tasks.emitter')
def emitter(self, string):
# emit to receive function in javascript... javascript pulls the 'mytext' field which contains (string)
self.emit('receive', {'mytext': string})
from socketio.namespace import BaseNamespace
import MainApp
MainApp.py
import app
class MainApp(app.TestClass):
def __init__(self):
self.emitter(self, 'test1234')
How can i use self.emit from TestClass in Mainapp? The emitter function runs self.emit that sends a string the the javascript code using websockets... I keep getting errors such as the following ...
TypeError: emitter() takes exactly 2 arguments (1 given)
OR in the case of the above...
Traceback (most recent call last):
File "/.../.../.../lib/python2.7/site-packages/gevent/greenlet.py", line 327, in run
result = self._run(*self.args, **self.kwargs)
File "/.../.../.../lib/python2.7/site-packages/socketio/virtsocket.py", line 403, in _receiver_loop
retval = pkt_ns.process_packet(pkt)
File "/.../.../.../lib/python2.7/site-packages/socketio/namespace.py", line 155, in process_packet
return self.process_event(packet)
File "/.../.../.../lib/python2.7/site-packages/socketio/namespace.py", line 225, in process_event
return self.call_method_with_acl(method_name, packet, *args)
File "/.../.../.../lib/python2.7/site-packages/socketio/namespace.py", line 240, in call_method_with_acl
return self.call_method(method_name, packet, *args)
File "/.../.../.../lib/python2.7/site-packages/socketio/namespace.py", line 282, in call_method
return method(*args)
File "/.../.../.../.../app/__init__.py", line 50, in on_submit
MainApp.MainApp()
File "/.../.../.../.../app/MainApp.py", line 11, in __init__
self.emitter(self, 'test1234')
File "/.../.../.../lib/python2.7/site-packages/celery/local.py", line 167, in <lambda>
__call__ = lambda x, *a, **kw: x._get_current_object()(*a, **kw)
File "/.../.../.../.../app/__init__.py", line 24, in __call__
return TaskBase.__call__(self, *args, **kwargs)
File "/.../.../.../lib/python2.7/site-packages/celery/app/task.py", line 420, in __call__
return self.run(*args, **kwargs)
File "/.../.../.../.../app/__init__.py", line 55, in emitter
self.emit('receive', {'mytext': string})
File "/.../.../.../lib/python2.7/site-packages/socketio/namespace.py", line 451, in emit
endpoint=self.ns_name)
AttributeError: 'MainApp' object has no attribute 'ns_name'
<Greenlet at 0x1120ad0f0: <bound method Socket._receiver_loop of <socketio.virtsocket.Socket object at 0x111c7c5d0>>> failed with AttributeError
Thanks!
I'd recommend that you explicitly create an instance of classA so avoid confusion.
class MainApp(object):
def __init__(self,emitter):
self.objA = ClassA()
self.emitter = self.objA.emitter
self.emitter('string')
You could also make it a class method, or a separate function if it needs shared:
#classmethod
#celery.task(name='tasks.emitter')
def emitter(cls, string):
cls.emit('receive', {'mytext': string})
class MainApp(object):
def __init__(self,emitter):
self.emitter = ClassA.emitter
self.emitter('string')
There is no issue here with it being in another class. Your MainApp class inherits from TestClass, so you are perfectly correct to refer to the method via self.emitter.
The only problem is that you are passing self twice: any method call, whether inherited or not, automatically passes the self argument, so you just need to pass the other argument:
self.emitter('test1234')
Looks like you are trying to do his backwards.
Per-condition: You need to define emit(someStr, someDict) somewhere.
Your MainClass need to extend ClassA.
Assuming you have class_a.py and main_app.py
main_app.py
from class_a import ClassA
class MainApp(ClassA):
## now you can call any method from ClassA
self.emitter(someArg)
Note: you don't need to MainApp.MainApp(self.emitter) in ClassA because MainApp extends ClassA.