Overriding library functions in Python

What you want to do is as the title says, so you can skip the introduction.

Background, introduction

I was writing an app to play with Google Calendar using the Google API Client Library. Drop the OAuth2 client information from Google Cloud Platform as client_secret.json and specify the ** file name ** in the argument of ʻoauth2client.client.flow_from_clientsecrets ()`.

The problem here. I don't want to add client_secret.json to git version control due to security concerns. However, I'm running the app on Heroku, so I can't upload files. (It seems that you should use object storage such as Amazon S3, but I stopped it because it is annoying because I have never used it)

So I had to specify client_secret.json, but I was having trouble putting that file on the Heroku server.

So, I want to put dictionary type data in ʻoauth2client.client.flow_from_clientsecrets () function instead of file name. Then, store the contents of client_secret.json` in the environment variables of Heroku and put them in the dictionary data. (Is it really bad to put confidential information in environment variables?)

Postscript

After writing the code, I realized that I should have created an instance of ʻOAuth2WebServerFlow` normally. Therefore, it is not necessary to override it separately, but I will leave it because I learned that it can be overridden in this way.

Thing you want to do

ʻOauth2client.client.flow_from_clientsecrets ()` I want the function to contain ** dictionary type ** instead of ** filename **.

What happened

The source code of the library looked like this. (The following is an excerpt from the Apache license code of Google Inc.)

Partially omitted from ʻoauth2client.client.py`.

@_helpers.positional(2)
def flow_from_clientsecrets(filename, scope, redirect_uri=None,
                            message=None, cache=None, login_hint=None,
                            device_uri=None, pkce=None, code_verifier=None):
    try:
        client_type, client_info = clientsecrets.loadfile(filename,
                                                          cache=cache)
        if client_type in (clientsecrets.TYPE_WEB,
        -----The following is omitted------

Note that filename is passed toclientsecrets.loadfile (). I also looked at clientsecrets.loadfile ().

def loadfile(filename, cache=None):
    _SECRET_NAMESPACE = 'oauth2client:secrets#ns'

    if not cache:
        return _loadfile(filename)

    obj = cache.get(filename, namespace=_SECRET_NAMESPACE)
    -----The following is omitted------

If cache does not exist, the processing is transferred to the _loadfile function. Let's take a look at _loadfile.

def _loadfile(filename):
    try:
        with open(filename, 'r') as fp:
            obj = json.load(fp)
    except IOError as exc:
        raise InvalidClientSecretsError('Error opening file', exc.filename,
                                        exc.strerror, exc.errno)
    return _validate_clientsecrets(obj)

I arrived at the function that is loading the file. If you override this function, you might put a dictionary type in the filename argument.

So after that my code

# `client.flow_from_clientsecrets`Functions can take dictionary type as arguments
# `clientsecrets._loadfile`Override function
def new_loadfile(data):
    return clientsecrets._validate_clientsecrets(data)
clientsecrets._loadfile = new_loadfile

After this

flow = client.flow_from_clientsecrets(
Dictionary type,
    scope='https://www.googleapis.com/auth/calendar',
    redirect_uri=flask.url_for('oauth2callback', _external=True))

You can now use flow_from_clientsecrets, which takes a dictionary type as an argument.

Summary

def new_func(args):
    #Various processing
    return hoge
hoge_library.func = new_func

This way it's easy to override and it affects all the functions that use that function.

Overriding library functions I did it for the first time, but it works so easily. I'm scared.

Recommended Posts

Overriding library functions in Python
Python functions learned in chemoinformatics
Python functions
[python] Manage functions in a list
Windows10: Install MeCab library in python
Using global variables in python functions
Dynamically define functions (methods) in Python
Python 3.6 email library
Quadtree in Python --2
Python in optimization
CURL in python
[Python, Julia] 3D display in Jupyter-Mayavi library
[Python3] Dynamically define global variables in functions
Metaprogramming in Python
Python 3.3 in Anaconda
Geocoding in python
SendKeys in Python
Meta-analysis in Python
Unittest in python
Easily use your own functions in Python
Pharmaceutical company researchers summarized functions in Python
Epoch in Python
Discord in Python
Sudoku in Python
DCI in Python
quicksort in python
nCr in python
Programming in python
What is "mahjong" in the Python library? ??
Plink in Python
Constant in python
Python Library notes
New features in Python 3.4.0 (3)-Single-dispatch generic functions
#Python basics (functions)
Lifegame in Python.
FizzBuzz in Python
Sqlite in python
[Beginner] Python functions
StepAIC in Python
N-gram in python
LINE-Bot [0] in Python
Csv in python
Disassemble in Python
Reflection in Python
Constant in python
nCr in Python.
format in python
Scons in Python3
Puyo Puyo in python
python in virtualenv
PPAP in Python
Python Easy-to-use functions
Quad-tree in Python
Python basics: functions
Reflection in Python
Chemistry in Python
Hashable in python
DirectLiNGAM in Python
LiNGAM in Python
Flatten in python
flatten in python