Programming while offline with Python
Tags: python, offline
Published: 2017-08-29 17:48:32

---
title: "Programming while offline with Python"
published: true
description: My personal experience about how to write code that's supposed to work online while offline
tags: Python, offline
cover_image: https://thepracticaldev.s3.amazonaws.com/i/gc5zrt9n7uhm6uzremmg.png
---

I live in Cuba. I've lived in Cuba since I was born and Cuba (believe me) is like kryptonite for software developers. Being one of the contries with less internet penetration (only 32.5% of the population has access to the internet) and having really high internet prices compared to average monthly income makes it really hard to be connected most of the time. Want more details? Check this OONI's [report](https://ooni.torproject.org/post/cuba-internet-censorship-2017/)
Nevertheless, we have great universities, and thousands graduate every year on thechnology careers. I was one of those. And one of the things that hits me harder is having sometimes to work with online resources with so poor or and expensive internet access, and since I love to code with Python, here is what I did.
I was coding a project where I needed to get some data from a service online and it was annoying since I was doing something as ugly and unmaintainable as:
```python
def doit():
    return 'false response'

    text_from_internet = get_data()
    return text_from_internet
```
And when I finally was online and going to test my work I commented the false return:
```python
def doit():
    # return 'false response'

    text_from_internet = get_data()
    return text_from_internet
```
This is so ugly I'm totally embarrassed to show you what I was doing. But I didn't stop. After some time using this ugly fix and having problems of all sort because I off course forguet to comment/unccoment my lines of junk code I decided to find a better way to do this and wrote my own decorator to handle this kind of problem:
```python
def offline_sandbox_value(value):
    def decorator(func):
        @wraps(func)
        def inner(*args, **kwargs):
            if SANDBOX:
                logging.debug('** Sandboxed ' + func.__name__ + '() with value: ' + value)
                return value
            else:
                return func(*args, **kwargs)

        return inner

    return decorator
```
It might look a little bit simple but this piece of code saves me hours of work. This is a decorator to set a default value to my functions when I'm offline. So imagine the first function, If I'm going to try my project offline y can define `SANDBOX = True` and decorate my function with a fake response:
```python
SANDBOX = True

@offline_sandbox_value('false response')
def doit():
    text_from_internet = get_data()
    return text_from_internet
```
And then switch SANDBOX to `False` whenever I'm running my code online.
This is useful if I'm interested in sandboxing everything (even when I do have access), but what if I want to check for the availability of a resource and sandbox the method if I can't reach a given URL? Well, let's do that:
```python
def offline_sandbox_value(value, url=None):
    def decorator(func):
        @wraps(func)
        def inner(*args, **kwargs):
            if url:
                if connect_to(url):
                    return func(*args, **kwargs)
                else:
                    logging.debug('** Sandboxed '+func.__name__+'() with value: '+value)
                    return value

            elif SANDBOX:
                logging.debug('** Sandboxed ' + func.__name__ + '() with value: ' + value)
                return value
            else:
                return func(*args, **kwargs)

        return inner

    return decorator
```
And now I can pass a URL to my decorator and I don't have to define a value for SANDBOX if I do. So my code would be something like:
```python
@offline_sandbox_value('false response', url='https://im-online.herokuapp.com/')
def doit():
    text_from_internet = get_data()
    return text_from_internet
```
And since I was using this on various projects and it has being very useful to me I decided to package it and uploade it to PyPi with the name [offline_sandbox](https://pypi.python.org/pypi?name=offline_sandbox&version=1&:action=display) so others can use it too. It's also on GitHub [here](https://github.com/jadolg/offline_sandbox) Do you want to contribute? Open an Issue or Pull Request :-) Thanks for reading.