Giter Club home page Giter Club logo

azure-functions-python-library's Introduction

Functions Header Image - Lightning Logo Azure Functions Python Library

Branch CodeCov
master codecov
dev codecov

Overview

Python support for Azure Functions is based on Python 3.7, 3.8, 3.9, 3.10, and 3.11, serverless hosting on Linux, and the Functions 2.x (EOL), 3.x (EOL) and 4.0 runtime.

Here is the current status of Python in Azure Functions:

What are the supported Python versions?

Azure Functions Runtime Python 3.6 Python 3.7 Python 3.8 Python 3.9 Python 3.10 Python 3.11
Azure Functions 3.0 EOL EOL EOL EOL - -
Azure Functions 4.0 EOL

What's available?

  • Build, test, debug and publish using Azure Functions Core Tools (CLI) or Visual Studio Code
  • Triggers / Bindings : HTTP, Blob, Queue, Timer, Cosmos DB, Event Grid, Event Hubs and Service Bus
  • Create a Python Function on Linux using a custom docker image
  • Triggers / Bindings : Custom binding support

Get Started

Give Feedback

Issues and feature requests are tracked in a variety of places. To report this feedback, please file an issue to the relevant repository below:

Item Description Link
Python Worker Programming Model, Triggers & Bindings File an Issue
Linux Base Docker Images File an Issue
Runtime Script Host & Language Extensibility File an Issue
VSCode VSCode Extension for Azure Functions File an Issue
Core Tools Command Line Interface for Local Development File an Issue
Portal User Interface or Experience Issue File an Issue
Templates Code Issues with Creation Template File an Issue

Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com.

When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

azure-functions-python-library's People

Contributors

ashiquemd avatar asottile avatar baluyotraf avatar brettcannon avatar bubbletroubles avatar charles-gagnon avatar davidmrdavid avatar elprans avatar evanr-dev avatar gavin-aguiar avatar hallvictoria avatar hazhzeng avatar hvt avatar lucyzhang929 avatar maiqbal11 avatar mcuckson avatar metamoof avatar michelole avatar microsoft-github-policy-service[bot] avatar microsoftopensource avatar msftgits avatar pamelafox avatar pdthummar avatar pragnagopa avatar shrohilla avatar t-eckert avatar tonybaloney avatar tsuyoshiushio avatar vrdmr avatar yunchuwang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

azure-functions-python-library's Issues

HTTP Request/Response headers should be multidict

Currently, all headers in request and response is dict. However, it should be multidict because there can be multiple items with the same key in HTTP headers. (i.e. multiple Set-Cookie headers to store multiple cookies)

The werkzeug implementation is based on custom implemented multidict.

class Headers(object):
"""An object that stores some headers. It has a dict-like interface
but is ordered and can store the same keys multiple times.

Retry policy removed from version 1.17.0

I am trying to implement the new v2 programming model for azure functions. I am using the latest stable (1.17.0), but I see that the retry options for functions is not present. I see however that it was available in version 1.16.0 and that it is available in the pre-release versions of 1.18.0.

Can I safely use version 1.16.0? Or was there a reason it was removed? Or should I wait for version 1.18?

WsgiMiddleware - Accidentally filled _wsgi_error_buffer by azure HttpLoggingPolicy logs?

Hi guys,

thank you for this #45 piece of code. I am using this to host my flask api in azure functions.
As I recently found out there seems to be an issue with the middleware in connection with KeyVault. In my opinion the HttpLoggingPolicy class in azu.core.pipeline.policies._universal uses the logging module to log the status of the http response. Unfortunately this populates the _wsgi_error_buffer in WsgiMiddleware (C:\Program Files\Microsoft\Azure Functions Core Tools\workers\python\3.8\WINDOWS\X64\azure\functions_http_wsgi.py).
When this buffer is filled with any content, then the handle_error function of the WsgiMiddleware raises an error with the content of the buffer.
I do not know why the buffer was filled. But it has to be connected because disabling the logger of the HttpLoggingPolicy (logging.getLogger('azure.core.pipeline.policies.http_logging_policy').setLevel(logging.ERROR)) solved the issue in local debugging. Unfortunately this didnt solve the issue in the deployed function.

Here are some details about the api endpoints, the access to the keyvault and the error message:

# az_func__init__.py
import azure.functions as func
from .app import create_app
from .config import app_config

connection = app_config['az_production']
app = create_app(connection)
application = app.wsgi_app


def main(req: func.HttpRequest, context: func.Context) -> func.HttpResponse:
    return func.WsgiMiddleware(application).handle(req, context)
# app.py.txt
from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient
from flask import Flask
from flask_restful import Resource
from flask_bcrypt import Bcrypt
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
db = SQLAlchemy()
bcrypt = Bcrypt()

class Endpoint(Resource):
  def get(self):
    vault_url = 'myVaultUrl'
    credentials = AzureCliCredential()
    secret_client = SecretClient(vault_url, credentials)
    secret = secret_client.get_secret("db-connection-str")
    return {'secret': secret}

def create_app(connection_obj):
    app.config.from_object(connection_obj)
    api = Api(app)
    bcrypt.init_app(app)
    db.init_app(app)
    db.create_all(app=app)
    api.add_resource(Endpoint, '/')

This is the error message (to get the error message I printed the exception in _http_wsgi.py - handle_error):

[2021-02-11T09:19:05.653] error_message: [2021-02-11 10:18:58,855] INFO in _universal: Response status: 401
[2021-02-11T09:19:05.739] Executed 'Functions.AdApi' (Failed, Id=0d594991-4412-4cef-9b1e-14f1d6f27602, Duration=13984ms)
[2021-02-11T09:19:05.742] System.Private.CoreLib: Exception while executing function: Functions.AdApi. System.Private.CoreLib: Result: Failure
Exception: Exception: [2021-02-11 10:18:58,855] INFO in _universal: Response status: 401

Stack: File "C:\Program Files\Microsoft\Azure Functions Core Tools\workers\python\3.8/WINDOWS/X64\azure_functions_worker\dispatcher.py", line 343, in _handle__invocation_request
call_result = await self._loop.run_in_executor(
File "C:\MyPrograms\Anaconda3\lib\concurrent\futures\thread.py", line 57, in run
result = self.fn(*self.args, **self.kwargs)
File "C:\Program Files\Microsoft\Azure Functions Core Tools\workers\python\3.8/WINDOWS/X64\azure_functions_worker\dispatcher.py", line 480, in _run_sync_func
return func(**params)
File "C:\Azure\dea-anomalydetection-prod-func\AdApi_init.py", line 19, in

main
raise ex
File "C:\Azure\dea-anomalydetection-prod-func\AdApi_init_.py", line 16, in main
return func.WsgiMiddleware(application).handle(req, context)
File "C:\Program Files\Microsoft\Azure Functions Core Tools\workers\python\3.8/WINDOWS/X64\azure\functions_http_wsgi.py", line 161, in handle
return self._handle(req, context)
File "C:\Program Files\Microsoft\Azure Functions Core Tools\workers\python\3.8/WINDOWS/X64\azure\functions_http_wsgi.py", line 174, in _handle
self._handle_errors()
File "C:\Program Files\Microsoft\Azure Functions Core Tools\workers\python\3.8/WINDOWS/X64\azure\functions_http_wsgi.py", line 184, in _handle_errors
raise Exception(error_message)

As you can see in the exception:
The content seems to be from "INFO in _universal:" So I disabled the logging of the function:
logger = logging.getLogger('azure.core.pipeline.policies.http_logging_policy')
logger.setLevel(logging.ERROR)
which solved the issue local (VS Studio Code) but not deployed

WsgiFunctionApp with DispatcherMiddleware and registering new HTTP triggers blueprints

Using a technique called DispatcherMiddleware it is possible to mount a Flask app only at an arbitrary prefix path.

Would it be possible for the http_app_func to manage only this mount path so that the app can register other HTTP endpoints (using durable functions and orchestrators for example)

import azure.functions as func
from werkzeug.serving import run_simple
from werkzeug.middleware.dispatcher import DispatcherMiddleware

flask_app = Flask(__name__)
@flask_app.get("/")
def hello():
    return Response(f"<h1>Hello World</h1>", mimetype="text/html")

flask_app.wsgi_app = DispatcherMiddleware(run_simple, {'/abc/123': flask_app.wsgi_app})
# see https://stackoverflow.com/a/18967744/1360476

app = func.WsgiFunctionApp(app=flask_app.wsgi_app, http_auth_level=func.AuthLevel.ANONYMOUS)
# app.register_blueprint(other_http_bp_here)

It appears every routes become managed by http_app_func because of the constant route template below.

@self.http_type(http_type='wsgi')
@self.route(methods=(method for method in HttpMethod),
auth_level=self.auth_level,
route="/{*route}")
def http_app_func(req: HttpRequest, context: Context):
return wsgi_middleware.handle(req, context)

Moreover using the host.json file it looks like it is only possible to set the $.extensions.http.routePrefix globally

https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-http-webhook?tabs=isolated-process%2Cfunctionsv2&pivots=programming-language-python#hostjson-settings

BUG: Cosmos DB Document should not be filtering _ts

The C# Function Extension for Cosmos DB returns documents that include some system properties, these are important for some use cases.

There is code that is filtering those system properties:

# Internal properties of CosmosDB documents.
_SYSTEM_KEYS = {'_etag', '_lsn', '_rid', '_self', '_ts'}
class Document(_abc.Document, collections.UserDict):
"""An Azure Document.
Document objects are ``UserDict`` subclasses and behave like dicts.
"""
@classmethod
def from_json(cls, json_data: str) -> 'Document':
"""Create a Document from a JSON string."""
return cls.from_dict(json.loads(json_data))
@classmethod
def from_dict(cls, dct: dict) -> 'Document':
"""Create a Document from a dict object."""
filtered = {k: v for k, v in dct.items() if k not in _SYSTEM_KEYS}
return cls(filtered)

Ideally that should not happen, users can depend on reading properties like _ts or _etag, or _lsn.

Unable to run an Azure Python function in VSCode

Please report the issue to Azure/azure-functions-python-worker via the following link:
https://github.com/Azure/azure-functions-python-worker/issues/new?assignees=&labels=&template=bug_report.md&title=%5BBUG%5D+Bug+Title

I have successfully created Azure Python Function V2, I am able to successfully launch the Azure Function from Terminal by running func host start command. However, when I try to run the Azure Function from VSCode with the Run and Debug option 'Attach To Python Functions' I am getting following error. Looking for guidance to troubleshoot the error.

Executing task: func host start --verbose --port 7072

Found Python version 3.10.12 (python3).

              %%%%%%
             %%%%%%
        @   %%%%%%    @
      @@   %%%%%%      @@
   @@@    %%%%%%%%%%%    @@@
 @@      %%%%%%%%%%        @@
   @@         %%%%       @@
     @@      %%%       @@
       @@    %%      @@
            %%
            %

Azure Functions Core Tools
Core Tools Version: 4.0.5530 Commit hash: N/A +c8883e7f3c06e2b424fbac033806c19d8d91418c (64-bit)
Function Runtime Version: 4.28.5.21962

[2024-03-26T03:21:08.968Z] Building host: version spec: , startup suppressed: 'False', configuration suppressed: 'False', startup operation id: '333306bc-6c60-4cfb-a72e-7c27d090dc1f'
[2024-03-26T03:21:08.975Z] Reading host configuration file '/home/linuxadmin/functest/host.json'
[2024-03-26T03:21:08.977Z] Host configuration file read:
[2024-03-26T03:21:08.977Z] {
[2024-03-26T03:21:08.978Z] "version": "2.0",
[2024-03-26T03:21:08.978Z] "logging": {
[2024-03-26T03:21:08.978Z] "applicationInsights": {
[2024-03-26T03:21:08.978Z] "samplingSettings": {
[2024-03-26T03:21:08.978Z] "isEnabled": true,
[2024-03-26T03:21:08.978Z] "excludedTypes": "Request"
[2024-03-26T03:21:08.978Z] }
[2024-03-26T03:21:08.978Z] }
[2024-03-26T03:21:08.979Z] },
[2024-03-26T03:21:08.979Z] "extensionBundle": {
[2024-03-26T03:21:08.979Z] "id": "Microsoft.Azure.Functions.ExtensionBundle",
[2024-03-26T03:21:08.979Z] "version": "[4.*, 5.0.0)"
[2024-03-26T03:21:08.979Z] }
[2024-03-26T03:21:08.979Z] }
[2024-03-26T03:21:09.019Z] FUNCTIONS_WORKER_RUNTIME set to python. Skipping WorkerConfig for language: powershell
[2024-03-26T03:21:09.019Z] FUNCTIONS_WORKER_RUNTIME set to python. Skipping WorkerConfig for language: node
[2024-03-26T03:21:09.067Z] FUNCTIONS_WORKER_RUNTIME set to python. Skipping WorkerConfig for language: java
[2024-03-26T03:21:09.068Z] Looking for extension bundle Microsoft.Azure.Functions.ExtensionBundle at /home/linuxadmin/.azure-functions-core-tools/Functions/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle
[2024-03-26T03:21:09.069Z] Found a matching extension bundle at /home/linuxadmin/.azure-functions-core-tools/Functions/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/4.13.2
[2024-03-26T03:21:09.093Z] Loading functions metadata
[2024-03-26T03:21:09.097Z] Worker indexing is enabled
[2024-03-26T03:21:09.108Z] Fetching metadata for workerRuntime: python
[2024-03-26T03:21:09.109Z] Reading functions metadata (Worker)
[2024-03-26T03:21:09.454Z] Language Worker Process exited. Pid=26321.
[2024-03-26T03:21:09.454Z] python3 exited with code 1 (0x1). log.reraise_exception("{0}() failed:", func.name, level="info"), raise RuntimeError(str(endpoints["error"])),RuntimeError: Can't listen for client connections: [Errno 98] Address already in use.
[2024-03-26T03:22:09.183Z] Starting worker process failed
[2024-03-26T03:22:09.185Z] Microsoft.Azure.WebJobs.Script.Grpc: The operation has timed out.
[2024-03-26T03:22:09.197Z] Failed to start language worker process for runtime: (null). workerId:eb0a9825-c9ea-432c-8e98-4c6c0dfe95b9

Can't import WsgiMiddleware

I just created a new functions project and tried to import WsgiMiddleware as mentioned in #45, but it won't resolve for some reason.

I'm using Python 3.7.4, core tools version 3.0.2245, and v1.2.0 of the azure-functions package

from azure.functions import (
    HttpRequest,
    HttpRequest,
    WsgiMiddleware,
    Context
)

def web_application(env, start_response, ):
    status = '200 OK'
    headers = [('Content-type', 'text/html')]
    start_response(status, headers)

    return[b'<strong>Raw WSGI application!!<strong>']


def main(req: HttpRequest,  context: Context) -> HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    return WsgiMiddleware(web_application).main(req, context)

Running the code above results in

[3/19/2020 8:10:25 AM]  INFO: Starting Azure Functions Python Worker.
[3/19/2020 8:10:25 AM]  INFO: Worker ID: 06c1081b-5d78-4298-9895-3171d3d6cb21, Request ID: e3580ac0-97a4-4504-b69c-674bdc108fc0, Host Address: 127.0.0.1:58404
[3/19/2020 8:10:25 AM]  INFO: Successfully opened gRPC channel to 127.0.0.1:58404
[3/19/2020 8:10:25 AM]  INFO: Received WorkerInitRequest, request ID e3580ac0-97a4-4504-b69c-674bdc108fc0
[3/19/2020 8:10:25 AM]  INFO: Received FunctionLoadRequest, request ID: e3580ac0-97a4-4504-b69c-674bdc108fc0, function ID: 09177bec-68a3-464d-8fef-59a47aa70125
[3/19/2020 8:10:25 AM]  INFO: Successfully processed FunctionLoadRequest, request ID: e3580ac0-97a4-4504-b69c-674bdc108fc0, function ID: 09177bec-68a3-464d-8fef-59a47aa70125
[3/19/2020 8:10:25 AM]  INFO: Received FunctionLoadRequest, request ID: e3580ac0-97a4-4504-b69c-674bdc108fc0, function ID: fa8828e4-d216-4ebc-9794-cbbcd9b70fed
[3/19/2020 8:10:25 AM] Worker failed to function id fa8828e4-d216-4ebc-9794-cbbcd9b70fed.
[3/19/2020 8:10:25 AM] Result: Failure
[3/19/2020 8:10:25 AM] Exception: ImportError: cannot import name 'WsgiMiddleware' from 'azure.functions' (/usr/local/Cellar/azure-functions-core-tools@3/3.0.2245/workers/python/3.7/OSX/X64/azure/functions/__init__.py)
[3/19/2020 8:10:25 AM] Stack:   File "/usr/local/Cellar/azure-functions-core-tools@3/3.0.2245/workers/python/3.7/OSX/X64/azure_functions_worker/dispatcher.py", line 242, in _handle__function_load_request
[3/19/2020 8:10:25 AM]     func_request.metadata.entry_point)
[3/19/2020 8:10:25 AM]   File "/usr/local/Cellar/azure-functions-core-tools@3/3.0.2245/workers/python/3.7/OSX/X64/azure_functions_worker/loader.py", line 66, in load_function
[3/19/2020 8:10:25 AM]     mod = importlib.import_module(fullmodname)
[3/19/2020 8:10:25 AM]   File "/Users/cecilphillip/.pyenv/versions/3.7.4/lib/python3.7/importlib/__init__.py", line 127, in import_module
[3/19/2020 8:10:25 AM]     return _bootstrap._gcd_import(name[level:], package, level)
[3/19/2020 8:10:25 AM]   File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
[3/19/2020 8:10:25 AM]   File "<frozen importlib._bootstrap>", line 983, in _find_and_load
[3/19/2020 8:10:25 AM]   File "<frozen importlib._bootstrap>", line 953, in _find_and_load_unlocked
[3/19/2020 8:10:25 AM]   File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
[3/19/2020 8:10:25 AM]   File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
[3/19/2020 8:10:25 AM]   File "<frozen importlib._bootstrap>", line 983, in _find_and_load
[3/19/2020 8:10:25 AM]   File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
[3/19/2020 8:10:25 AM]   File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
[3/19/2020 8:10:25 AM]   File "<frozen importlib._bootstrap_external>", line 728, in exec_module
[3/19/2020 8:10:25 AM]   File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
[3/19/2020 8:10:25 AM]   File "/Users/cecilphillip/Desktop/toss/WsgiApi/__init__.py", line 1, in <module>
[3/19/2020 8:10:25 AM]     from azure.functions import (
[3/19/2020 8:10:25 AM] .
[3/19/2020 8:10:25 AM] Host restarted.
[3/19/2020 8:10:25 AM] Stopping 

@Hazhzeng am I missing something?

Can't change default function name while using FastAPI

I've been trying to set a custom name while using FastAPI and couldn't find the proper way. It always deploys my function with the name "http_app_func," making deploying multiple functions to the same app impossible.

Has anyone been successful with this task?

This is the syntax I thought it would work:

app = func.AsgiFunctionApp(app=fastapi_app, http_auth_level=func.AuthLevel.FUNCTION).function_name(name="HttpTest")

Inconsistent naming get_json() in EventGridEvent and EventGridOutputEvent

Both mentioned classes have methods called get_json which return the classes __data field. This seems odd for two reasons:

  1. They don't actually return JSON but a dict (if the typing hints in __init__ are correct). In any case this is a major source of confusion.
  2. All other getters are implemented as properties. (So why not just do the same here?)

def get_json(self) -> typing.Any:
return self.__data

def get_json(self) -> typing.Any:
return self.__data

[FeatureRequest] add to_dict to func.Document for CosmosDB

Describe the request: A clear and concise description.
It would be great to add a to_dict method to the Document class so that you can immediately pass that into a class constructor with ** and not have to do json.reads(doc.to_json())

UploadFile not working with FastAPI Integration

Afternoon,

We have an azure function using v2 and fastapi integration:

function_app.py

from typing import List
import logging
import azure.functions as func
import fastapi


fastapi_app = fastapi.FastAPI()
@fastapi_app.post("/api/asdf")
async def asdf(file: fastapi.UploadFile = fastapi.File(None)):
    logging.info(str(file))

app = func.AsgiFunctionApp(app=fastapi_app, http_auth_level=func.AuthLevel.ANONYMOUS)

The logging always print None, even I am posting file with file key.

HTTP payloads get modified by Function when content-type is application/json

From @asavaritayal on December 11, 2018 6:39

From @brettcannon on December 10, 2018 19:46

Investigative information

Please provide the following:

  • Timestamp :2018-11-28 20:25:05.885
  • Function App name: pvscbot
  • Function name(s) (as appropriate): github

Repro steps

POST an application/json HTTP payload with a body of b'{"action": "opened"}'.

Expected behavior

Get the exact HTTP payload in the Function.

Actual behavior

Get a POST payload of b'{\n "action": "opened"\n}' (notice the pretty-printing).

Known workarounds

None.

Related information

This pretty-printing of JSON breaks HTTP payload signatures. In my specific case, this breaks the HMAC signature provided by GitHub webhooks. This is critical as it prevents malicious users from trying to force a bot to do something it shouldn't (as bots typically have write access and can do things like commit and deploy code). It also breaks checking for any man-in-the-middle attacks by verifying the signature against the HTTP payload.

You could theoretically add a key as a GET parameter, but then that exposes the shared secret in logs (compared to an HMAC signature which pulls a secret from an environment variable that Key Vault stores on the Function's behalf), so that is not a tenable solution when security is the aim here.

Copied from original issue: Azure/azure-functions-python-worker#260

Copied from original issue: Azure/azure-functions-host#3875

WsgiMiddleware does not handle Flask Response status code and headers properly

When using the WsgiMiddleware class to hand off the http request to a Flask application, the response metadata, such as the http status code and headers do not get propagated to the caller.

Testing locally

$ curl -I http://127.0.0.1:5000/?rate=wrongvalue
HTTP/1.0 400 BAD REQUEST
Content-Type: text/html; charset=utf-8
Content-Length: 19
Server: Werkzeug/1.0.1 Python/3.8.7
Date: Thu, 11 Mar 2021 12:24:48 GMT

Testing the deployed version

$ curl -I https://<function-app>.azurewebsites.net/?rate=wrongvalue
HTTP/1.1 200 OK
Content-Length: 149793
Content-Type: text/html
Server: Kestrel
Request-Context: appId=cid-v1:185d53a8-5b98-4639-822a-9265563316df
Date: Thu, 11 Mar 2021 12:57:59 GMT

Sample code to reproduce:

entry point

import azure.functions as func
from app import app


def main(req: func.HttpRequest, context: func.Context) -> func.HttpResponse:
    return func.WsgiMiddleware(app.wsgi_app).handle(req, context)

function.json

{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "get",
        "post"
      ],
      "route": "{*route}"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    }
  ]
}

flask app

import json
from flask import Flask, Response, request
from flask_restful import reqparse
from werkzeug.exceptions import BadRequest

app = Flask(__name__)

@app.route("/")
def index():
    parser = reqparse.RequestParser()
    parser.add_argument("rate", type=int, help="Rate cannot be converted")
    parser.add_argument("name")
    try:
        args = parser.parse_args()
    except BadRequest:
        return Response(
            "Bad Request",
            status=400,
        )

    return Response(
        json.dumps(args),
        content_type="application/json; charset=utf-8",
    )

if __name__ == "__main__":
    app.run(debug=True)

host.json

{
  "version": "2.0",
  "logging": {
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": true,
        "excludedTypes": "Request"
      }
    }
  },
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[1.*, 2.0.0)"
  },
  "extensions": {
    "http": {
      "routePrefix": ""
    }
  }
}

Trigger refusing the sync of deployed azure function (WSGI)

I made an azure function that uses the WSGI support in azure functions. It's a simple python application that uses flask and chatterbot library to run a chatbot in the browser. The project runs fine locally but when I deploy it to Azure (runtime version 3.0.15149.0 running python 3.7.9 USGovVirginiaLinuxDynamicPlan) the triggers refuse to sync after following the instructions of the author.

I thought I had found a workaround but I was mistaken and was wondering if anyone could point me in the right direction.

Here is my function.json:

{
  "scriptFile": "__init__.py",  
  "bindings": [  
    {  
      "route": "/{*route}",
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    }
  ]
}

My route uses a wildcard catch-all per the author's instructions. Also, like the author, I made the routeprefix blank (to remove the "api" prefix). This is the output I end up getting at the end of my deployment

4:45:27 AM chatterbot: Number of duplicate files found 698
4:45:27 AM chatterbot: Number of inodes 14092
4:45:27 AM chatterbot: Number of files 12722
4:45:27 AM chatterbot: Number of fragments 1086
4:45:27 AM chatterbot: Number of symbolic links  0
4:45:27 AM chatterbot: Number of device nodes 0
4:45:27 AM chatterbot: Number of fifo nodes 0
4:45:27 AM chatterbot: Number of socket nodes 0
4:45:27 AM chatterbot: Number of directories 1370
4:45:28 AM chatterbot: Number of ids (unique uids + gids) 1
4:45:28 AM chatterbot: Number of uids 1
4:45:28 AM chatterbot: 	root (0)
4:45:28 AM chatterbot: Number of gids 1
4:45:28 AM chatterbot: 	root (0)
4:45:28 AM chatterbot: Uploading built content /home/site/artifacts/functionappartifact.squashfs for linux consumption function app...
4:45:31 AM chatterbot: Resetting all workers for [removed url]
4:45:47 AM chatterbot: Syncing triggers...
4:46:06 AM chatterbot: Syncing triggers (Attempt 2/6)...
4:46:17 AM chatterbot: Syncing triggers (Attempt 3/6)...
4:46:39 AM chatterbot: Syncing triggers (Attempt 4/6)...
4:47:19 AM chatterbot: Syncing triggers (Attempt 5/6)...
4:48:57 AM chatterbot: Syncing triggers (Attempt 6/6)...
4:48:59 AM: Error: Encountered an error (InternalServerError) from host runtime.

It attempts to sync the triggers a few times and fails. I'm not sure if this is an issue specific to the Linux deployment of USGov or if the route wildcard required to get this WSGI functionality is not supported but if anyone had any pointers I would appreciate it.

HttpRequest.files performance issue

I'm attempting write a simple Azure Function that reads an XML file sent in using multipart/form-data as seen in the below curl sample (the file is about 7.5MB).

curl --location --request POST 'http://localhost:7071/api/HttpTrigger1' \
--header 'Content-Type: multipart/form-data' \
--form 'gpxFile=@/C:/somefile.XML'

When I use this line of code using the Azure Functions Python Library to access the data:
x = req.files.get('gpxFile').stream.read().decode("utf-8")
I'm seeing about 15 second response times.

A similar line using Flask:
x = request.files['gpxFile'].read().decode("utf-8")
returns in about 1.5 seconds.

Am I using the HttpRequest object incorrectly? If not, why does Flask request respond so much quicker then the Azure HttpRequest?

Support HTTPStatus IntEnum for status code return values.

I wound up using the HTTPStatus IntEnum for a status code in my func.HttpResponse returns but noticed the actual web response I was getting was always 200, even when doing something like status_code=HTTPStatus.BAD_REQUEST.

Just to verify, I did confirm that returning int(HTTPStatus.BAD_REQUEST) on my side of things seemed to fix. So maybe this is addressable in the azure-functions-python-library code (not even sure if it is a worker thing in the first place).

Minor, but it would be convenient to be able to use HTTPStatus. Thought I'd suggest the enhancement since it caused me some head scratching to figure out why I was getting 200's that didn't make sense and it should be an easy tweak.

[BUG] AsgiMiddleware starts an event loop which is never closed

Timestamp: Tue 31 Oct 2022 10:45 CET
Python azure-functions v1.10

The current AsgiMiddleware class starts a new event loop in its constructor. As can be seen here:

self._loop = asyncio.new_event_loop()

The deprecated handle() method was responsible for closing this loop once a request was handled.

A better handle_async() method replaced this solution and was introduced here:

https://github.com/Azure/azure-functions-python-library/pull/143/files

But the new solution does not use and never closes the loop created in the constructor

Expected behavior

Starting an event loop is not trivial and opens file resources. These won't be closed when using the new solution. When using the handle_async method there is no need to start a new event loop. If an event loop is needed for backward compatibility in the deprecated handle method, it should be created and stopped in the deprecated method and not in the init.

Queue messages get their id from body of message.

I am not sure if this is intentional but if a message contains an "Id" field it seems to be used as the id property in QueueMessage. I assume that this has something to do with how the contents of trigger_metadata are set (I am unable to identify the origin of the argument). I assume this because of how it is being extacted in QueueMessageInConverter and the fact that my messages arrive with the same body['Id'] and msg.id.

Maybe I am completly wrong but I am curious if this is intentional or aviodable somehow, if not I would like to open a discussion about it.

I personally did not expect this behaviour and it required a ugly workaround.

[BUG] Service Bus Session ID is not available to Function code

Investigative information

Please provide the following:

IcM: 283549053 has an impacted function app with relevant detail

Repro steps

  1. Create a Function App that triggers off a Service bus session enabled queue.
Provide the steps required to reproduce the problem:

Expected behavior

Provide a description of the expected behavior.

Actual behavior

Provide a description of the actual behavior observed.

Known workarounds

Provide a description of any known workarounds.

Fetch the session id from the nested field in the message:
msg.metadata["MessageSession"]["SessionId"]

Contents of the requirements.txt file:

Provide the requirements.txt file to help us find out module related issues.

N/A

Related information

Provide any related information
  • Bindings used: Service Bus
def main(msg: func.ServiceBusMessage):
    logging.info('Python ServiceBus queue trigger processed message: %s',
                 msg.get_body().decode('utf-8'))
    logging.info('Python msg.session_id - : %s', msg.metadata["MessageSession"]["SessionId"])
    logging.info('Python msg.session_id1 - : %s', msg.session_id)

Output

[2022-02-09T00:36:58.242Z] Python msg.session_id - : {12229E1-B37B-4D29-AA0A-E367906C206E}
[2022-02-09T00:36:58.242Z] Python msg.session_id1 - : None

The location where library sets session_id.

curl -H "Authorization: SharedAccessSignature sr=SERVICE_BUS.servicebus.windows.net%2FINPUT_QUEUE&sig=XXXXXX&se=YYY&skn=RootManageSharedAccessKey"  \
  -H 'BrokerProperties: {"SessionId": "{12229E1-B37B-4D29-AA0A-E367906C206E}"}' \
  -H "Content-Type: application/json" \
  -d "HelloWorld" \
  -X POST -i "https://servicebus-test-vameru.servicebus.windows.net/myinputqueue/messages\?timeout\=60"

HTTP/1.1 201 Created
Transfer-Encoding: chunked
Content-Type: application/xml; charset=utf-8
Server: Microsoft-HTTPAPI/2.0
Strict-Transport-Security: max-age=31536000
Date: Wed, 09 Feb 2022 00:36:57 GMT

The Complete Metadata

{
    "UserProperties": {},
    "DeliveryCount": 1,
    "LockToken": "fc949e24-410f-4a78-853b-7b8ce125cb99",
    "MessageSession": {
        "LockedUntilUtc": "2022-02-08T22: 30: 52.33697Z",
        "SessionId": "{17729E1-B37B-4D29-AA0A-E367906C206E}",
        "RegisteredPlugins": [],
        "ReceiveMode": 0,
        "PrefetchCount": 0,
        "LastPeekedSequenceNumber": 0,
        "Path": "myinputqueue",
        "OperationTimeout": "00: 01: 00",
        "ServiceBusConnection": {
            "Endpoint": "sb://servicebus-test-vameru.servicebus.windows.net",
            "OperationTimeout": "00:01:00",
            "RetryPolicy": {
                "MinimalBackoff": "00:00:00",
                "MaximumBackoff": "00:00:30",
                "DeltaBackoff": "00:00:03",
                "MaxRetryCount": 5,
                "IsServerBusy": False,
                "ServerBusyExceptionMessage": None
            },
            "TransportType": 0,
            "TokenProvider": {},
            "IsClosedOrClosing": False
        },
        "IsClosedOrClosing": False,
        "OwnsConnection": False,
        "ClientId": "MessageSession27myinputqueue_{17729E1-B37B-4D29-AA0A-E367906C206E}",
        "RetryPolicy": {
            "MinimalBackoff": "00:00:00",
            "MaximumBackoff": "00:00:30",
            "DeltaBackoff": "00:00:03",
            "MaxRetryCount": 5,
            "IsServerBusy": False,
            "ServerBusyExceptionMessage": None
        }
    },
    "ContentType": "application/json",
    "SequenceNumber": 13,
    "MessageReceiver": {
        "LockedUntilUtc": "2022-02-08T22:30:52.33697Z",
        "SessionId": "{17729E1-B37B-4D29-AA0A-E367906C206E}",
        "RegisteredPlugins": [],
        "ReceiveMode": 0,
        "PrefetchCount": 0,
        "LastPeekedSequenceNumber": 0,
        "Path": "myinputqueue",
        "OperationTimeout": "00:01:00",
        "ServiceBusConnection": {
            "Endpoint": "sb://servicebus-test-vameru.servicebus.windows.net",
            "OperationTimeout": "00:01:00",
            "RetryPolicy": {
                "MinimalBackoff": "00:00:00",
                "MaximumBackoff": "00:00:30",
                "DeltaBackoff": "00:00:03",
                "MaxRetryCount": 5,
                "IsServerBusy": False,
                "ServerBusyExceptionMessage": None
            },
            "TransportType": 0,
            "TokenProvider": {},
            "IsClosedOrClosing": False
        },
        "IsClosedOrClosing": False,
        "OwnsConnection": False,
        "ClientId": "MessageSession27myinputqueue_{17729E1-B37B-4D29-AA0A-E367906C206E}",
        "RetryPolicy": {
            "MinimalBackoff": "00:00:00",
            "MaximumBackoff": "00:00:30",
            "DeltaBackoff": "00:00:03",
            "MaxRetryCount": 5,
            "IsServerBusy": False,
            "ServerBusyExceptionMessage": None
        }
    },
    "EnqueuedTimeUtc": "2022-02-08T22:22:19.292Z",
    "ExpiresAtUtc": "2022-02-22T22:22:19.292Z",
    "MessageId": "806c77a2924441fe855697d39647e096"
}

Question: Azure Functions Python library Development Cycle

Hi,

I've a quick question regarding the development cycle of the Azure Functions Python library and it's integration with other Azure services like Azure Functions App: In the documentation for Python developers using Azure Functions (link here) it mentions that each worker includes a new version of Azure Functions Python library, but that the runtime library version is fixed by Azure, and it can't be overridden. The current version is 1.3.0 on Functions App, but the latest release of the library is 1.3.1 with some very useful features. So, my question is:

When will the latest release of the Azure Functions Python library be added to the Azure Functions App worker nodes?

Thanks,
Vinny

The load execution start time and program start gap is large - Azure Function APP

I am trying to implement Asynchronous Azure Function App using python. When I am testing the simple code with load noticing a larger time gap in execution start time and program start time. Below mention main two components are there in the code -

  1. Connection with Postgres DB object.
  2. One loop which is taking around 200ms time.

Let me know how to solve this problem

Multiple Output Messages to Service Bus

For the Queue output binding it is possible to send multiple messages to the same output, see Azure Documentation. In a similar fashion I would like to be able to do the same for Service Bus Messages.

My use case is to implement an Azure Function based on a timer which scrapes some data from an API and sends multiple messages to the same service bus topic. In a very basic example my function would look like this

__init__.py

import typing
import azure.functions as func

def main(mytimer: func.TimerRequest, outputmessage: func.Out[typing.List[str]]):
    outputmessage.set(["Message 1","Message 2"])

function.json

{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "name": "mytimer",
      "type": "timerTrigger",
      "direction": "in",
      "schedule": "0 */1 * * * *"
    },
    {
      "type": "serviceBus",
      "direction": "out",
      "connection": "AzureServiceBusConnectionString",
      "name": "outputmessage",
      "topicName": "mytopic2"
    }
  ]
}

Currently this is not allowed as the ServiceBusMessageOutConverter only allows for a str or bytes type. I converted both methods encode and check_output_type_annotation to allow for collections in a similar fashion to the Queue Binding and when I run the function locally it is able to create multiple output messages to the same binding.

Is this something that can easily be added to the library (I would be willing to submit a PR) or is this approach breaking something?

Support for ASGI applications

Hello.

I've been looking into how to use ASGI applications with Azure Functions. I maintain a library called Mangum that at one point in time supported Azure Functions, but currently only supports AWS Lambda. I've received some interest in supporting multiple serverless platforms (such as Azure) again, but noticed this library now offers support for WSGI so figured I'd raise the issue here.

Would it be desirable to include support for ASGI applications in this library? This would enable a number of ASGI application frameworks to be used in a similar way to WSGI.

I migrated the removed Azure Function support from Mangum into a different project, Bonnette, which allowed using ASGI like this:

import logging
import azure.functions as func
from bonnette import Bonnette


async def app(scope, receive, send):
    assert scope["type"] == "http"
    await send(
        {
            "type": "http.response.start",
            "status": 200,
            "headers": [[b"content-type", b"text/html; charset=utf-8"]],
        }
    )
    await send(
        {"type": "http.response.body", "body": b"<html><h1>Hello, world!</h1></html>"}
    )


def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info("Python HTTP trigger function processed a request.")
    handler = Bonnette(app)
    return handler(req)

There is some incorrect behaviour in that project around the ASGI request/response handling (it is unmaintained), but maybe it can help serve as a reference for the Azure Functions. Additionally the implementation here might be helpful, there are a few AWS-specific things but mostly it handles only the HTTP->ASGI behaviour.

Anyway, I'm not using Azure Functions myself so beyond what I've mentioned above I don't have a lot of interest in supporting this externally, but still wanted to help find a solution for users of frameworks like FastAPI that have expressed interest.

How to receive CloudEvent triggers?

EventGrid can send events in CloudEvents v1 format - but how do I receive them in a function? I expected to see a func.CloudEvent just like func.EventGridEvent or some transformation, but "CloudEvent" yields 0 hits in this repo.

get_json() seems to give me the payload (.data), but what about the metadata? What about extension attributes?

Implement read1 method for InputStream

Description

InputStream inherits from BufferedIOBase which defines a read1 method to return an arbitrary amount of bytes instead of everything till EOF. libraries like pandas provide functions to read from a io stream and they seem to be calling read1 method internally on the stream. They throw an error when InputStream is directly passed

Reproducible Example

import pandas as pd
from azure.functions.blob import InputStream

def error():
    i = InputStream(data=b'a,b,c,d\n1,2,3,4')
    # This throws read1() UnsupportedOperation exception
    df = pd.read_csv(i, sep=",")

def hack():
    i = InputStream(data=b'a,b,c,d\n1,2,3,4')

    def read1(self, size: int = -1) -> bytes:
        return self.read(size)

    setattr(InputStream, 'read1', read1)
    
    # This works because we hacked read1 method into InputStream
    with pd.read_csv(i, sep=",", chunksize=1) as reader:
        for chunk in reader:
            print(chunk)
            
if __name__ == "__main__":
    hack()
    error()

versions:
python=3.7
pandas=1.2.4

Use cases

  • being able to read and process buffered streams of CSV-like files in pandas can be more memory efficient?
  • makes InputStream more compatible with other libraries reading IOStreams

References

someone had implemented read1 in ABC of the python-worker repo in this PR. seems like details are lost in a forced push (This might be unrelated, not sure)

Auto-Args to main in Azure function App are not generated at new bindings

@srikkar commented on Mon Mar 16 2020

  • Package Name: Azure func core tools
  • Package Version: 2.7.2254
  • Operating System: Windows
  • Python Version: 3.6

Describe the bug
Have followed this URL: https://docs.microsoft.com/en-us/azure/python/tutorial-vs-code-serverless-python-07 to get the auto bindings generated. But, still after following the steps, I couldn’t get the auto generated arguments

To Reproduce
Steps to reproduce the behavior:

  1. Follow the Steps as per URL above for Cosmos DB in binding with HTTPTrigger

Expected behavior
After Adding the new in binding to HTTPTrigger Azure function, expect SDK to auto-generate Args to access the data from Cosmos Graph/SQL inside function's main

Azure python binding Args

Additional context
Any suggestions to get the data from grapgh DB using Gremlin API are most welcome


@msftbot[bot] commented on Tue Mar 17 2020

Thanks for the feedback! We are routing this to the appropriate team for follow-up. cc @ahmedelnably, @fabiocav.

Python - azure.functions.WsgiMiddleware does not support multiple Set-Cookie response headers

Bug

When a HttpResponse has multiple headers with the same name, only one header is returned.
Django uses multiple response cookies (e.g. 'csrf' and 'messages').
Multiple Set-Cookie headers can be returned. Set-Cookie is the name (the key) of the Http Response Header.

Context

A Django app running in an Azure Function

package

Name: azure-functions
Version: 1.8.0
Summary: Azure Functions for Python
Home-page: UNKNOWN
Author: Microsoft Corporation
Author-email: [email protected]

Version

Azure function runtime version = ~4

Reproduction

  1. Create a http response with two Set-Cookie headers
    This header has been captured from the app running without the Azure wsgi middleware.
HTTP/1.1 200 OK
Date: Sun, 16 Jan 2022 09:00:59 GMT
Server: WSGIServer/0.2 CPython/3.9.9
Content-Type: text/html; charset=utf-8
X-Frame-Options: DENY
Vary: Cookie
Content-Length: 5206
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
Set-Cookie:  messages=""; expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; Max-Age=0; Path=/; SameSite=Lax
Set-Cookie:  csrftoken=L6coOZOclDhAg2X7geBKbhvJSHPxz9AbgOkoVqNAIsgVe8oxTEPTSPbc2VPSyjwq; expires=Sun, 15 Jan 2023 09:00:59 GMT; Max-Age=31449600; Path=/; SameSite=Lax
  1. Run without azure.functions.WsgiMiddleware
    Two Set-Cookies headers are returned (as depicted above)

  2. Run with azure.functions.WsgiMiddleware.handle

import azure.functions as func
def main(req: func.HttpRequest, context: func.Context) -> func.HttpResponse:
    http_response = func.WsgiMiddleware(application).handle(req, context)
    return http_response

Only one header with the name "Set-Cookie" is returned.

Local and remote

This behaviour has been reproduced both locally (while debugging) as on an Azure Function container (icarus-int)

Root cause

Python package 'azure-functions'
azure\functions_http.py

class HttpResponseHeaders(BaseHeaders, collections.abc.MutableMapping):

    def __setitem__(self, key: str, value: str):
        self.__http_headers__[key.lower()] = value

    def __delitem__(self, key: str):
        del self.__http_headers__[key.lower()]

The headers are stored as a dictionary. All keys in a dictionary are unique.

References

https://www.rfc-editor.org/rfc/rfc6265#page-6
Section 3

"Origin servers SHOULD NOT fold multiple Set-Cookie header fields into
a single header field. The usual mechanism for folding HTTP headers
fields (i.e., as defined in [RFC2616]) might change the semantics of
the Set-Cookie header field because the %x2C (",") character is used
by Set-Cookie in a way that conflicts with such folding."

https://www.rfc-editor.org/rfc/rfc6265#section-4.1
"Servers SHOULD NOT include more than one Set-Cookie header field in
the same response with the same cookie-name. (See Section 5.2 for
how user agents handle this case.)"

This means that multiple Set-Cookie headers with different cookie-names are allowed.

annotations for WsgiMiddleware cause app to not be startable

$ ./node_modules/.bin/func host start --python --functions MyFunction
Found Python version 3.8.2 (python3).
Azure Functions Core Tools (3.0.2912 Commit hash: bfcbbe48ed6fdacdf9b309261ecc8093df3b83f2)
Function Runtime Version: 3.0.14287.0
Hosting environment: Production
Content root path: /home/asottile/workspace/pre-commit-ci/azure-sample-application
Now listening on: http://0.0.0.0:7071
Application started. Press Ctrl+C to shut down.

Functions:

	MyFunction: [GET,POST] http://localhost:7071/api/MyFunction

For detailed output, run func with --verbose flag.
Worker process started and initialized.
Worker failed to function id 6333f1be-d5f7-4f0d-8cb8-e8ed6f42210a.
Result: Failure
Exception: FunctionLoadError: cannot load the MyFunction function: the "context" parameter is expected to be of type azure.functions.Context, got typing.Union[azure.functions._abc.Context, NoneType]
Stack:   File "/home/asottile/workspace/pre-commit-ci/azure-sample-application/node_modules/azure-functions-core-tools/bin/workers/python/3.8/LINUX/X64/azure_functions_worker/dispatcher.py", line 268, in _handle__function_load_request
    self._functions.add_function(
  File "/home/asottile/workspace/pre-commit-ci/azure-sample-application/node_modules/azure-functions-core-tools/bin/workers/python/3.8/LINUX/X64/azure_functions_worker/functions.py", line 105, in add_function
    raise FunctionLoadError(
import azure.functions
import flask

app = flask.Flask(__name__)


@app.route('/', methods=['GET'])
def index() -> str:
    return 'hello hello world'


main = azure.functions.WsgiMiddleware(app).main

it looks like it is being a little too strict on the typing here

the @property is annotated correctly here

but the function it returns, uses Optional[Context] instead here

mypy allows this because the _handler is a more-permissive compatible signature, but the func tool forbids this (incorrectly)

I can work around this by wrapping the function trivially -- another alternative would be to make main call that instead of having a property (this would incur a function call overhead per call though, but that's probably ok?) -- that would be the easiest patch without having to refactor the type checking code in func

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.