I have the following code

import time
from flask import Flask, request
from flask_restful import Resource, Api
import threading

app = Flask(__name__)
api = Api(app)

class A:
    def __init__(self):
        self.x = 5

    def increment_x(self):
        self.x += 1

    def get_x(self):
        return self.x

def a_runner(b):
    while True:

class B:
    def __init__(self, ref: A):
        class GetAssetPairs(Resource):
            def __init__(self, int_ref: A):
                self.inst_of_A = int_ref

            def get(self):
                return {'test': self.inst_of_A.get_x()}

        api.add_resource(GetAssetPairs, '/test', resource_class_kwargs={'int_ref': ref})
        app.run(port='5003', debug=False)

if __name__ == "__main__":
    b = A()
    bot_th = threading.Thread(target=a_runner, args=(b,), daemon=True)
    c = B(b)

Is there a more proper way to have access to functions of class A through the REST Api instead of passing it to the Resource class using the resource_class_kwargs? This implementation works but feels like it's a hack and not very scalable if the API grows.

  • \$\begingroup\$ Why the downvote? \$\endgroup\$ – po.pe Dec 16 '19 at 11:19
  • 1
    \$\begingroup\$ Is this code from a real project? If not, your question is off-topic. You may want to attend the help center to inform yourself what questions can be asked here. \$\endgroup\$ – πάντα ῥεῖ Dec 16 '19 at 12:01
  • \$\begingroup\$ This code smells hypothetical, hence the downvotes and requests for closing the question. Please take a look at the help center to see what is and isn't an acceptable question here. Thank you. \$\endgroup\$ – Mast Dec 16 '19 at 12:57
  • \$\begingroup\$ I'll do, sorry for that. It's not hypothetical as such, the project is just growing and I used this as a system design verification. \$\endgroup\$ – po.pe Dec 16 '19 at 13:04
  • \$\begingroup\$ I'm not sure what you mean with that. Does this mean the current code is a mock-up, a proof-of-concept? \$\endgroup\$ – Mast Dec 16 '19 at 14:26

The initial approach is over-complicated and has issues in design, namings and relations.

Class A

The get_x method makes no sense for returning public attribute self.x value - that x attribute is accessible directly. Instead, it's better to apply @property decorator (provides a "getter" for a read-only attribute with the same name) to "protected" self._x attribute/field.

The a_runner function is coupled/dependent on specific behavior (increment_x, get_x) inherent to class A instance. Thus, it's better and reasonably moved to be a part of class A scope. Time delay can be flexibly used/adjusted via additional keyword argument with default value delay=5

The optimized class A definition:

class A:
    def __init__(self, init_value=5):
        self._x = init_value

    def increment_x(self):
        self._x += 1

    def x(self):
        return self._x

    def run(self, delay=5):
        while True:

Class B

Flask API is usually declared at top level as api = Api(app) and it's absolutely normal to add/register resources api.add_resource at the same level. Class B is redundant as itself.
Class GetAssetPairs is defined as top-level class for custom resource. Using resource_class_kwargs feature is normal and designed for that cases.

The rest part, optimized:

class GetAssetPairs(Resource):
    def __init__(self, a_instance: A):
        self.a_instance = a_instance

    def get(self):
        return {'test': self.a_instance.x}

if __name__ == "__main__":
    a = A()
    bot_th = threading.Thread(target=a.run, daemon=True)

    api.add_resource(GetAssetPairs, '/test', resource_class_kwargs={'a_instance': a})
    app.run(port='5003', debug=False)
  • 2
    \$\begingroup\$ In the future, please refrain from answering off-topic questions. There are plenty of questions within the current site-scope that could use an answer instead. Please take a look at the help center. \$\endgroup\$ – Mast Dec 16 '19 at 12:58

Not the answer you're looking for? Browse other questions tagged or ask your own question.