Define a general method for remote and local data

I have some Python code that accesses data locally or remotely. To demonstrate this, the example below fetches a todo item from a remote JSON API or from a local JSON file. The _remote_todo method fetches the todo item from the JSON API. The _local_todo fetches the item from a local JSON file. The get_todo method provides a single interface to locally or remotely get the todo item. Instead of defining three methods is there a way to consolidate this into one method? Maybe there is a way to define the local function and decorate it with the API call? Is there a design pattern that would lend itself well to this type of problem? I’m eager to know if there is a better way to write local and remote code in Python.

import json
import requests

class Todo:
    def __init__(self, item_id: int):
        self.item_id = item_id

    def _remote_todo(self):
        api = f"https://jsonplaceholder.typicode.com/todos/{self.item_id}"
        resp = requests.get(api)
        print(resp.json())

    def _local_todo(self):
        with open("todos.json") as f:
            data = json.load(f)

        for d in data:
            if d["id"] == self.item_id:
                print(d)

    def get_todo(self, api: bool = False):
        if api:
            self._remote_todo()
        else:
            self._local_todo()

def main():
    """Run example."""
    todo = Todo(item_id=2)
    todo.get_todo(api=True)
    todo.get_todo()

if __name__ == "__main__":
    main()

The method that fetches locally and the method that fetches remotely are doing different things. Why do you want to cram their functionalities into one method?

What you have currently is simple to understand, and it works.

I’m not sure about the name of the api keyword, though. Maybe remote would be a better name.

1 Like

You could have Todo be an abstract class then RemoteTodo and LocalTodo classes that each implement the same methods but do it differently.

That would be using inheritance.

Though honestly what you have now is simpler. Inheritance would come in handy if there winds up being a lot of other functions, etc. that act slightly different but have the same functionality/name. In a case of a single function, an if statement is probably fine.

My concern is that adding more functions will quickly increase the number of methods on the class. For example, to add a function that gets a post would be something like this which requires three more methods:

def _remote_post(self):
    ...

def _local_post(self):
    ...

def get_post(self, remote: bool = False):
    ...

I was thinking that a decorator could be used (like shown below) with the local function to decrease the number of methods in the class.

# Get the post from local data file

def get_post(self):
    ...

# Get the post from remote API

@remote
def get_post(self):
    ...