Decorate a python function to work as a Google Cloud Function The 2019 Stack Overflow Developer Survey Results Are In

Why does the nucleus not repel itself?

Worn-tile Scrabble

Why isn't the circumferential light around the M87 black hole's event horizon symmetric?

Is it ok to offer lower paid work as a trial period before negotiating for a full-time job?

Is it a good practice to use a static variable in a Test Class and use that in the actual class instead of Test.isRunningTest()?

Likelihood that a superbug or lethal virus could come from a landfill

Why doesn't UInt have a toDouble()?

How do you keep chess fun when your opponent constantly beats you?

What do I do when my TA workload is more than expected?

Is an up-to-date browser secure on an out-of-date OS?

What does もの mean in this sentence?

Is it okay to consider publishing in my first year of PhD?

Can a flute soloist sit?

Can I have a signal generator on while it's not connected?

"as much details as you can remember"

What is this sharp, curved notch on my knife for?

Why don't hard Brexiteers insist on a hard border to prevent illegal immigration after Brexit?

Why was M87 targeted for the Event Horizon Telescope instead of Sagittarius A*?

Can withdrawing asylum be illegal?

What is the most efficient way to store a numeric range?

Does HR tell a hiring manager about salary negotiations?

How to obtain a position of last non-zero element

If my opponent casts Ultimate Price on my Phantasmal Bear, can I save it by casting Snap or Curfew?

Cooking pasta in a water boiler



Decorate a python function to work as a Google Cloud Function



The 2019 Stack Overflow Developer Survey Results Are In



.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








0












$begingroup$


I wrote this for a class project, the backend for this dog voting website. I noticed duplicate code among multiple functions I was writing to be deployed as a cloud function: they all were wrapped in try/except blocks that returned either 200 and JSON or 500 and a traceback. (I understand that it would be better to return an informative, structured error code, but this helped with debugging and we didn't have extensive error handling on the front-end: this was a loss I was willing to take).



The decorator gives each function a connection pool, uses jsonschema to validate input and output, responds to CORS OPTIONS from anywhere, and uses print statements for logging. This isn't great, but it was far easier to set up than the Google Cloud Function logging library, and everything printed to stdout during function execution is logged to GCP Stackdriver.



Here is the decorator itself:



import functools
import json
import traceback

import jsonschema
from util.get_pool import get_pool

pg_pool = None


def cloudfunction(in_schema=None, out_schema=None):
"""

:param in_schema: the schema for the input, or a falsy value if there is no input
:param out_schema: the schema for the output, or a falsy value if there is no output
:return: the cloudfunction wrapped function
"""
# Both schemas must be valid according to jsonschema draft 7, if they are provided.
if in_schema:
jsonschema.Draft7Validator.check_schema(in_schema)
if out_schema:
jsonschema.Draft7Validator.check_schema(out_schema)

def cloudfunction_decorator(f):
""" Wraps a function with two arguments, the first of which is a json object that it expects to be sent with the
request, and the second is a postgresql pool. It modifies it by:
- setting CORS headers and responding to OPTIONS requests with `Allow-Origin *`
- passing a connection from a global postgres connection pool
- adding logging, of all inputs as well as error tracebacks.

:param f: A function that takes a `request` and a `pgpool` and returns a json-serializable object
:return: a function that accepts one argument, a Flask request, and calls f with the modifications listed
"""

@functools.wraps(f)
def wrapped(request):
global pg_pool

if request.method == 'OPTIONS':
return cors_options()

# If it's not a CORS OPTIONS request, still include the base header.
headers = 'Access-Control-Allow-Origin': '*'

if not pg_pool:
pg_pool = get_pool()

try:
conn = pg_pool.getconn()

if in_schema:
request_json = request.get_json()
print(repr("request_json": request_json))
jsonschema.validate(request_json, in_schema)
function_output = f(request_json, conn)
else:
function_output = f(conn)

if out_schema:
jsonschema.validate(function_output, out_schema)

conn.commit()
print(repr("response_json": function_output))

response_json = json.dumps(function_output)
# TODO allow functions to specify return codes in non-exceptional cases
return (response_json, 200, headers)
except:
print("Error: Exception traceback: " + repr(traceback.format_exc()))
return (traceback.format_exc(), 500, headers)
finally:
# Make sure to put the connection back in the pool, even if there has been an exception
try:
pg_pool.putconn(conn)
except NameError: # conn might not be defined, depending on where the error happens above
pass

return wrapped

return cloudfunction_decorator


# If given an OPTIONS request, tell the requester that we allow all CORS requests (pre-flight stage)
def cors_options():
# Allows GET and POST requests from any origin with the Content-Type
# header and caches preflight response for an 3600s
headers =
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Max-Age': '3600'


return ('', 204, headers)


get_pool is here:



from os import getenv
from psycopg2 import OperationalError, connect
from psycopg2.pool import SimpleConnectionPool

INSTANCE_CONNECTION_NAME = getenv('INSTANCE_CONNECTION_NAME', "")

POSTGRES_USER = getenv('POSTGRES_USER', "")
POSTGRES_PASSWORD = getenv('POSTGRES_PASSWORD', "")
POSTGRES_NAME = getenv('POSTGRES_DATABASE', "postgres")

pg_config =
'user': POSTGRES_USER,
'password': POSTGRES_PASSWORD,
'dbname': POSTGRES_NAME



def get_pool():
try:
return __connect(f'/cloudsql/INSTANCE_CONNECTION_NAME')
except OperationalError:
# If production settings fail, use local development ones
return __connect('localhost')


def __connect(host):
"""
Helper functions to connect to Postgres
"""
pg_config['host'] = host
return SimpleConnectionPool(1, 1, **pg_config)


def get_connection(host="localhost"):
pg_config["host"] = host
return connect(**pg_config)


And an example of usage:




@cloudfunction(
in_schema="type": "string",
out_schema=
"anyOf": [
"type": "object",
"properties":
"dog1": "type": "integer",
"dog2": "type": "integer"
,
"additionalProperties": False,
"minProperties": 2,
,
"type": "null"
]
)
def get_dog_pair(request_json, conn):
[function body elided]








share







New contributor




Julian Zucker is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$


















    0












    $begingroup$


    I wrote this for a class project, the backend for this dog voting website. I noticed duplicate code among multiple functions I was writing to be deployed as a cloud function: they all were wrapped in try/except blocks that returned either 200 and JSON or 500 and a traceback. (I understand that it would be better to return an informative, structured error code, but this helped with debugging and we didn't have extensive error handling on the front-end: this was a loss I was willing to take).



    The decorator gives each function a connection pool, uses jsonschema to validate input and output, responds to CORS OPTIONS from anywhere, and uses print statements for logging. This isn't great, but it was far easier to set up than the Google Cloud Function logging library, and everything printed to stdout during function execution is logged to GCP Stackdriver.



    Here is the decorator itself:



    import functools
    import json
    import traceback

    import jsonschema
    from util.get_pool import get_pool

    pg_pool = None


    def cloudfunction(in_schema=None, out_schema=None):
    """

    :param in_schema: the schema for the input, or a falsy value if there is no input
    :param out_schema: the schema for the output, or a falsy value if there is no output
    :return: the cloudfunction wrapped function
    """
    # Both schemas must be valid according to jsonschema draft 7, if they are provided.
    if in_schema:
    jsonschema.Draft7Validator.check_schema(in_schema)
    if out_schema:
    jsonschema.Draft7Validator.check_schema(out_schema)

    def cloudfunction_decorator(f):
    """ Wraps a function with two arguments, the first of which is a json object that it expects to be sent with the
    request, and the second is a postgresql pool. It modifies it by:
    - setting CORS headers and responding to OPTIONS requests with `Allow-Origin *`
    - passing a connection from a global postgres connection pool
    - adding logging, of all inputs as well as error tracebacks.

    :param f: A function that takes a `request` and a `pgpool` and returns a json-serializable object
    :return: a function that accepts one argument, a Flask request, and calls f with the modifications listed
    """

    @functools.wraps(f)
    def wrapped(request):
    global pg_pool

    if request.method == 'OPTIONS':
    return cors_options()

    # If it's not a CORS OPTIONS request, still include the base header.
    headers = 'Access-Control-Allow-Origin': '*'

    if not pg_pool:
    pg_pool = get_pool()

    try:
    conn = pg_pool.getconn()

    if in_schema:
    request_json = request.get_json()
    print(repr("request_json": request_json))
    jsonschema.validate(request_json, in_schema)
    function_output = f(request_json, conn)
    else:
    function_output = f(conn)

    if out_schema:
    jsonschema.validate(function_output, out_schema)

    conn.commit()
    print(repr("response_json": function_output))

    response_json = json.dumps(function_output)
    # TODO allow functions to specify return codes in non-exceptional cases
    return (response_json, 200, headers)
    except:
    print("Error: Exception traceback: " + repr(traceback.format_exc()))
    return (traceback.format_exc(), 500, headers)
    finally:
    # Make sure to put the connection back in the pool, even if there has been an exception
    try:
    pg_pool.putconn(conn)
    except NameError: # conn might not be defined, depending on where the error happens above
    pass

    return wrapped

    return cloudfunction_decorator


    # If given an OPTIONS request, tell the requester that we allow all CORS requests (pre-flight stage)
    def cors_options():
    # Allows GET and POST requests from any origin with the Content-Type
    # header and caches preflight response for an 3600s
    headers =
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Headers': 'Content-Type',
    'Access-Control-Max-Age': '3600'


    return ('', 204, headers)


    get_pool is here:



    from os import getenv
    from psycopg2 import OperationalError, connect
    from psycopg2.pool import SimpleConnectionPool

    INSTANCE_CONNECTION_NAME = getenv('INSTANCE_CONNECTION_NAME', "")

    POSTGRES_USER = getenv('POSTGRES_USER', "")
    POSTGRES_PASSWORD = getenv('POSTGRES_PASSWORD', "")
    POSTGRES_NAME = getenv('POSTGRES_DATABASE', "postgres")

    pg_config =
    'user': POSTGRES_USER,
    'password': POSTGRES_PASSWORD,
    'dbname': POSTGRES_NAME



    def get_pool():
    try:
    return __connect(f'/cloudsql/INSTANCE_CONNECTION_NAME')
    except OperationalError:
    # If production settings fail, use local development ones
    return __connect('localhost')


    def __connect(host):
    """
    Helper functions to connect to Postgres
    """
    pg_config['host'] = host
    return SimpleConnectionPool(1, 1, **pg_config)


    def get_connection(host="localhost"):
    pg_config["host"] = host
    return connect(**pg_config)


    And an example of usage:




    @cloudfunction(
    in_schema="type": "string",
    out_schema=
    "anyOf": [
    "type": "object",
    "properties":
    "dog1": "type": "integer",
    "dog2": "type": "integer"
    ,
    "additionalProperties": False,
    "minProperties": 2,
    ,
    "type": "null"
    ]
    )
    def get_dog_pair(request_json, conn):
    [function body elided]








    share







    New contributor




    Julian Zucker is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.







    $endgroup$














      0












      0








      0





      $begingroup$


      I wrote this for a class project, the backend for this dog voting website. I noticed duplicate code among multiple functions I was writing to be deployed as a cloud function: they all were wrapped in try/except blocks that returned either 200 and JSON or 500 and a traceback. (I understand that it would be better to return an informative, structured error code, but this helped with debugging and we didn't have extensive error handling on the front-end: this was a loss I was willing to take).



      The decorator gives each function a connection pool, uses jsonschema to validate input and output, responds to CORS OPTIONS from anywhere, and uses print statements for logging. This isn't great, but it was far easier to set up than the Google Cloud Function logging library, and everything printed to stdout during function execution is logged to GCP Stackdriver.



      Here is the decorator itself:



      import functools
      import json
      import traceback

      import jsonschema
      from util.get_pool import get_pool

      pg_pool = None


      def cloudfunction(in_schema=None, out_schema=None):
      """

      :param in_schema: the schema for the input, or a falsy value if there is no input
      :param out_schema: the schema for the output, or a falsy value if there is no output
      :return: the cloudfunction wrapped function
      """
      # Both schemas must be valid according to jsonschema draft 7, if they are provided.
      if in_schema:
      jsonschema.Draft7Validator.check_schema(in_schema)
      if out_schema:
      jsonschema.Draft7Validator.check_schema(out_schema)

      def cloudfunction_decorator(f):
      """ Wraps a function with two arguments, the first of which is a json object that it expects to be sent with the
      request, and the second is a postgresql pool. It modifies it by:
      - setting CORS headers and responding to OPTIONS requests with `Allow-Origin *`
      - passing a connection from a global postgres connection pool
      - adding logging, of all inputs as well as error tracebacks.

      :param f: A function that takes a `request` and a `pgpool` and returns a json-serializable object
      :return: a function that accepts one argument, a Flask request, and calls f with the modifications listed
      """

      @functools.wraps(f)
      def wrapped(request):
      global pg_pool

      if request.method == 'OPTIONS':
      return cors_options()

      # If it's not a CORS OPTIONS request, still include the base header.
      headers = 'Access-Control-Allow-Origin': '*'

      if not pg_pool:
      pg_pool = get_pool()

      try:
      conn = pg_pool.getconn()

      if in_schema:
      request_json = request.get_json()
      print(repr("request_json": request_json))
      jsonschema.validate(request_json, in_schema)
      function_output = f(request_json, conn)
      else:
      function_output = f(conn)

      if out_schema:
      jsonschema.validate(function_output, out_schema)

      conn.commit()
      print(repr("response_json": function_output))

      response_json = json.dumps(function_output)
      # TODO allow functions to specify return codes in non-exceptional cases
      return (response_json, 200, headers)
      except:
      print("Error: Exception traceback: " + repr(traceback.format_exc()))
      return (traceback.format_exc(), 500, headers)
      finally:
      # Make sure to put the connection back in the pool, even if there has been an exception
      try:
      pg_pool.putconn(conn)
      except NameError: # conn might not be defined, depending on where the error happens above
      pass

      return wrapped

      return cloudfunction_decorator


      # If given an OPTIONS request, tell the requester that we allow all CORS requests (pre-flight stage)
      def cors_options():
      # Allows GET and POST requests from any origin with the Content-Type
      # header and caches preflight response for an 3600s
      headers =
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Headers': 'Content-Type',
      'Access-Control-Max-Age': '3600'


      return ('', 204, headers)


      get_pool is here:



      from os import getenv
      from psycopg2 import OperationalError, connect
      from psycopg2.pool import SimpleConnectionPool

      INSTANCE_CONNECTION_NAME = getenv('INSTANCE_CONNECTION_NAME', "")

      POSTGRES_USER = getenv('POSTGRES_USER', "")
      POSTGRES_PASSWORD = getenv('POSTGRES_PASSWORD', "")
      POSTGRES_NAME = getenv('POSTGRES_DATABASE', "postgres")

      pg_config =
      'user': POSTGRES_USER,
      'password': POSTGRES_PASSWORD,
      'dbname': POSTGRES_NAME



      def get_pool():
      try:
      return __connect(f'/cloudsql/INSTANCE_CONNECTION_NAME')
      except OperationalError:
      # If production settings fail, use local development ones
      return __connect('localhost')


      def __connect(host):
      """
      Helper functions to connect to Postgres
      """
      pg_config['host'] = host
      return SimpleConnectionPool(1, 1, **pg_config)


      def get_connection(host="localhost"):
      pg_config["host"] = host
      return connect(**pg_config)


      And an example of usage:




      @cloudfunction(
      in_schema="type": "string",
      out_schema=
      "anyOf": [
      "type": "object",
      "properties":
      "dog1": "type": "integer",
      "dog2": "type": "integer"
      ,
      "additionalProperties": False,
      "minProperties": 2,
      ,
      "type": "null"
      ]
      )
      def get_dog_pair(request_json, conn):
      [function body elided]








      share







      New contributor




      Julian Zucker is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.







      $endgroup$




      I wrote this for a class project, the backend for this dog voting website. I noticed duplicate code among multiple functions I was writing to be deployed as a cloud function: they all were wrapped in try/except blocks that returned either 200 and JSON or 500 and a traceback. (I understand that it would be better to return an informative, structured error code, but this helped with debugging and we didn't have extensive error handling on the front-end: this was a loss I was willing to take).



      The decorator gives each function a connection pool, uses jsonschema to validate input and output, responds to CORS OPTIONS from anywhere, and uses print statements for logging. This isn't great, but it was far easier to set up than the Google Cloud Function logging library, and everything printed to stdout during function execution is logged to GCP Stackdriver.



      Here is the decorator itself:



      import functools
      import json
      import traceback

      import jsonschema
      from util.get_pool import get_pool

      pg_pool = None


      def cloudfunction(in_schema=None, out_schema=None):
      """

      :param in_schema: the schema for the input, or a falsy value if there is no input
      :param out_schema: the schema for the output, or a falsy value if there is no output
      :return: the cloudfunction wrapped function
      """
      # Both schemas must be valid according to jsonschema draft 7, if they are provided.
      if in_schema:
      jsonschema.Draft7Validator.check_schema(in_schema)
      if out_schema:
      jsonschema.Draft7Validator.check_schema(out_schema)

      def cloudfunction_decorator(f):
      """ Wraps a function with two arguments, the first of which is a json object that it expects to be sent with the
      request, and the second is a postgresql pool. It modifies it by:
      - setting CORS headers and responding to OPTIONS requests with `Allow-Origin *`
      - passing a connection from a global postgres connection pool
      - adding logging, of all inputs as well as error tracebacks.

      :param f: A function that takes a `request` and a `pgpool` and returns a json-serializable object
      :return: a function that accepts one argument, a Flask request, and calls f with the modifications listed
      """

      @functools.wraps(f)
      def wrapped(request):
      global pg_pool

      if request.method == 'OPTIONS':
      return cors_options()

      # If it's not a CORS OPTIONS request, still include the base header.
      headers = 'Access-Control-Allow-Origin': '*'

      if not pg_pool:
      pg_pool = get_pool()

      try:
      conn = pg_pool.getconn()

      if in_schema:
      request_json = request.get_json()
      print(repr("request_json": request_json))
      jsonschema.validate(request_json, in_schema)
      function_output = f(request_json, conn)
      else:
      function_output = f(conn)

      if out_schema:
      jsonschema.validate(function_output, out_schema)

      conn.commit()
      print(repr("response_json": function_output))

      response_json = json.dumps(function_output)
      # TODO allow functions to specify return codes in non-exceptional cases
      return (response_json, 200, headers)
      except:
      print("Error: Exception traceback: " + repr(traceback.format_exc()))
      return (traceback.format_exc(), 500, headers)
      finally:
      # Make sure to put the connection back in the pool, even if there has been an exception
      try:
      pg_pool.putconn(conn)
      except NameError: # conn might not be defined, depending on where the error happens above
      pass

      return wrapped

      return cloudfunction_decorator


      # If given an OPTIONS request, tell the requester that we allow all CORS requests (pre-flight stage)
      def cors_options():
      # Allows GET and POST requests from any origin with the Content-Type
      # header and caches preflight response for an 3600s
      headers =
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Headers': 'Content-Type',
      'Access-Control-Max-Age': '3600'


      return ('', 204, headers)


      get_pool is here:



      from os import getenv
      from psycopg2 import OperationalError, connect
      from psycopg2.pool import SimpleConnectionPool

      INSTANCE_CONNECTION_NAME = getenv('INSTANCE_CONNECTION_NAME', "")

      POSTGRES_USER = getenv('POSTGRES_USER', "")
      POSTGRES_PASSWORD = getenv('POSTGRES_PASSWORD', "")
      POSTGRES_NAME = getenv('POSTGRES_DATABASE', "postgres")

      pg_config =
      'user': POSTGRES_USER,
      'password': POSTGRES_PASSWORD,
      'dbname': POSTGRES_NAME



      def get_pool():
      try:
      return __connect(f'/cloudsql/INSTANCE_CONNECTION_NAME')
      except OperationalError:
      # If production settings fail, use local development ones
      return __connect('localhost')


      def __connect(host):
      """
      Helper functions to connect to Postgres
      """
      pg_config['host'] = host
      return SimpleConnectionPool(1, 1, **pg_config)


      def get_connection(host="localhost"):
      pg_config["host"] = host
      return connect(**pg_config)


      And an example of usage:




      @cloudfunction(
      in_schema="type": "string",
      out_schema=
      "anyOf": [
      "type": "object",
      "properties":
      "dog1": "type": "integer",
      "dog2": "type": "integer"
      ,
      "additionalProperties": False,
      "minProperties": 2,
      ,
      "type": "null"
      ]
      )
      def get_dog_pair(request_json, conn):
      [function body elided]






      python python-3.x web-services google-cloud-platform





      share







      New contributor




      Julian Zucker is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.










      share







      New contributor




      Julian Zucker is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.








      share



      share






      New contributor




      Julian Zucker is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      asked 3 mins ago









      Julian ZuckerJulian Zucker

      1012




      1012




      New contributor




      Julian Zucker is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      Julian Zucker is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      Julian Zucker is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.




















          0






          active

          oldest

          votes












          Your Answer





          StackExchange.ifUsing("editor", function ()
          return StackExchange.using("mathjaxEditing", function ()
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          );
          );
          , "mathjax-editing");

          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "196"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );






          Julian Zucker is a new contributor. Be nice, and check out our Code of Conduct.









          draft saved

          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f217303%2fdecorate-a-python-function-to-work-as-a-google-cloud-function%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown

























          0






          active

          oldest

          votes








          0






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          Julian Zucker is a new contributor. Be nice, and check out our Code of Conduct.









          draft saved

          draft discarded


















          Julian Zucker is a new contributor. Be nice, and check out our Code of Conduct.












          Julian Zucker is a new contributor. Be nice, and check out our Code of Conduct.











          Julian Zucker is a new contributor. Be nice, and check out our Code of Conduct.














          Thanks for contributing an answer to Code Review Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          Use MathJax to format equations. MathJax reference.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f217303%2fdecorate-a-python-function-to-work-as-a-google-cloud-function%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          名間水力發電廠 目录 沿革 設施 鄰近設施 註釋 外部連結 导航菜单23°50′10″N 120°42′41″E / 23.83611°N 120.71139°E / 23.83611; 120.7113923°50′10″N 120°42′41″E / 23.83611°N 120.71139°E / 23.83611; 120.71139計畫概要原始内容臺灣第一座BOT 模式開發的水力發電廠-名間水力電廠名間水力發電廠 水利署首件BOT案原始内容《小檔案》名間電廠 首座BOT水力發電廠原始内容名間電廠BOT - 經濟部水利署中區水資源局

          Prove that NP is closed under karp reduction?Space(n) not closed under Karp reductions - what about NTime(n)?Class P is closed under rotation?Prove or disprove that $NL$ is closed under polynomial many-one reductions$mathbfNC_2$ is closed under log-space reductionOn Karp reductionwhen can I know if a class (complexity) is closed under reduction (cook/karp)Check if class $PSPACE$ is closed under polyonomially space reductionIs NPSPACE also closed under polynomial-time reduction and under log-space reduction?Prove PSPACE is closed under complement?Prove PSPACE is closed under union?

          Is my guitar’s action too high? Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern)Strings too stiff on a recently purchased acoustic guitar | Cort AD880CEIs the action of my guitar really high?Μy little finger is too weak to play guitarWith guitar, how long should I give my fingers to strengthen / callous?When playing a fret the guitar sounds mutedPlaying (Barre) chords up the guitar neckI think my guitar strings are wound too tight and I can't play barre chordsF barre chord on an SG guitarHow to find to the right strings of a barre chord by feel?High action on higher fret on my steel acoustic guitar