Skip to content

Commit

Permalink
Merge branch 'release/1.3.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
Hanzhang Zeng (Roger) committed Jul 1, 2020
2 parents ac94476 + 633acd8 commit 01075c7
Show file tree
Hide file tree
Showing 40 changed files with 1,197 additions and 88 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
<img src="https://raw.githubusercontent.com/Azure/azure-functions-python-worker/dev/docs/Azure.Functions.svg" width = "180" alt="Functions Header Image">

|Branch|Status|Coverage|
|---|---|---|
|master|[![Build Status](https://azfunc.visualstudio.com/Azure%20Functions%20Python/_apis/build/status/Azure%20Functions%20Python-CI?branchName=master)](https://azfunc.visualstudio.com/Azure%20Functions%20Python/_build/latest?definitionId=19&branchName=master)|![Azure DevOps coverage](https://img.shields.io/azure-devops/coverage/azfunc/Azure%20Functions%20Python/19/master)
|dev|[![Build Status](https://azfunc.visualstudio.com/Azure%20Functions%20Python/_apis/build/status/Azure%20Functions%20Python-CI?branchName=dev)](https://azfunc.visualstudio.com/Azure%20Functions%20Python/_build/latest?definitionId=19&branchName=dev)|![Azure DevOps coverage](https://img.shields.io/azure-devops/coverage/azfunc/Azure%20Functions%20Python/19/dev)

# Overview

Python support for Azure Functions is based on Python 3.6/3.7/3.8, serverless hosting on Linux and the Functions 2.0 runtime.

Here is the current status of Python in Azure Functions:

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

# Contributing

Expand Down
81 changes: 46 additions & 35 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
@@ -1,38 +1,49 @@
trigger:
- master
- dev
- master
- dev

schedules:
- cron: "0 8 * * 1,3,5"
displayName: Monday, Wednesday and Friday - 1 AM (PDT) build
branches:
include:
- dev
- master
exclude:
- release/*
- releases/ancient/*

jobs:
- job: Tests
pool:
vmImage: 'ubuntu-16.04'
strategy:
matrix:
Python36:
pythonVersion: '3.6'
Python37:
pythonVersion: '3.7'
Python38:
pythonVersion: '3.8'
maxParallel: 3
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '$(pythonVersion)'
addToPath: true
- task: ShellScript@2
inputs:
disableAutoCwd: true
scriptPath: .ci/build.sh
displayName: 'Build'
- bash: |
chmod +x .ci/run_tests.sh
.ci/run_tests.sh
displayName: 'Run Tests'
- task: PublishCodeCoverageResults@1
inputs:
codeCoverageTool: cobertura
summaryFileLocation: coverage.xml
- bash: |
rm coverage.xml
displayName: 'Clearing coverage.xml file'
- job: Tests
pool:
vmImage: 'ubuntu-16.04'
strategy:
matrix:
Python36:
pythonVersion: '3.6'
Python37:
pythonVersion: '3.7'
Python38:
pythonVersion: '3.8'
maxParallel: 3
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '$(pythonVersion)'
addToPath: true
- task: ShellScript@2
inputs:
disableAutoCwd: true
scriptPath: .ci/build.sh
displayName: 'Build'
- bash: |
chmod +x .ci/run_tests.sh
.ci/run_tests.sh
displayName: 'Run Tests'
- task: PublishCodeCoverageResults@1
inputs:
codeCoverageTool: cobertura
summaryFileLocation: coverage.xml
- bash: |
rm coverage.xml
displayName: 'Clearing coverage.xml file'
4 changes: 4 additions & 0 deletions azure/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

from pkgutil import extend_path
import typing

__path__: typing.Iterable[str] = extend_path(__path__, __name__)
11 changes: 10 additions & 1 deletion azure/functions/__init__.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

from ._abc import TimerRequest, InputStream, Context, Out # NoQA
from ._eventhub import EventHubEvent # NoQA
from ._eventgrid import EventGridEvent, EventGridOutputEvent # NoQA
from ._cosmosdb import Document, DocumentList # NoQA
from ._http import HttpRequest # NoQA
from ._http import HttpResponse # NoQA
from ._http_wsgi import WsgiMiddleware # NoQA
from .kafka import KafkaEvent, KafkaConverter, KafkaTriggerConverter # NoQA
from ._queue import QueueMessage # NoQA
from ._servicebus import ServiceBusMessage # NoQA
from ._durable_functions import OrchestrationContext # NoQA
from .meta import get_binding_registry # NoQA

# Import binding implementations to register them
from . import blob # NoQA
from . import cosmosdb # NoQA
from . import eventgrid # NoQA
from . import eventhub # NoQA
from . import http # NoQA
from . import kafka # NoQA
from . import queue # NoQA
from . import servicebus # NoQA
from . import timer # NoQA
Expand All @@ -37,6 +43,9 @@
'HttpRequest',
'HttpResponse',
'InputStream',
'KafkaEvent',
'KafkaConverter',
'KafkaTriggerConverter',
'OrchestrationContext',
'QueueMessage',
'ServiceBusMessage',
Expand All @@ -46,4 +55,4 @@
'WsgiMiddleware'
)

__version__ = '1.2.1'
__version__ = '1.3.0'
3 changes: 3 additions & 0 deletions azure/functions/_abc.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

import abc
import datetime
import io
Expand Down
3 changes: 3 additions & 0 deletions azure/functions/_cosmosdb.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

import collections
import json

Expand Down
6 changes: 4 additions & 2 deletions azure/functions/_durable_functions.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

from typing import Union
from . import _abc
from importlib import import_module
Expand Down Expand Up @@ -33,12 +36,11 @@ def _serialize_custom_object(obj):
"function")
# Encode to json using the object's `to_json`
obj_type = type(obj)
dict_obj = {
return {
"__class__": obj.__class__.__name__,
"__module__": obj.__module__,
"__data__": obj_type.to_json(obj)
}
return dict_obj


def _deserialize_custom_object(obj: dict) -> object:
Expand Down
3 changes: 3 additions & 0 deletions azure/functions/_eventgrid.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

import datetime
import typing

Expand Down
38 changes: 36 additions & 2 deletions azure/functions/_eventhub.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,37 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

import datetime
import typing

from azure.functions import _abc as funcabc
from azure.functions import _abc as func_abc
from azure.functions import meta


class EventHubEvent(funcabc.EventHubEvent):
class EventHubEvent(func_abc.EventHubEvent):
"""A concrete implementation of Event Hub message type."""

def __init__(self, *,
body: bytes,
trigger_metadata: typing.Mapping[str, meta.Datum] = None,
enqueued_time: typing.Optional[datetime.datetime] = None,
partition_key: typing.Optional[str] = None,
sequence_number: typing.Optional[int] = None,
offset: typing.Optional[str] = None,
iothub_metadata: typing.Optional[
typing.Mapping[str, str]] = None) -> None:
self.__body = body
self.__trigger_metadata = trigger_metadata
self.__enqueued_time = enqueued_time
self.__partition_key = partition_key
self.__sequence_number = sequence_number
self.__offset = offset
self.__iothub_metadata = iothub_metadata

# Cache for trigger metadata after Python object conversion
self._trigger_metadata_pyobj: typing.Optional[
typing.Mapping[str, typing.Any]] = None

def get_body(self) -> bytes:
return self.__body

Expand All @@ -45,6 +55,30 @@ def enqueued_time(self) -> typing.Optional[datetime.datetime]:
def offset(self) -> typing.Optional[str]:
return self.__offset

@property
def metadata(self) -> typing.Optional[typing.Mapping[str, typing.Any]]:
"""Getting read-only trigger metadata in a Python dictionary.
Exposing the raw trigger_metadata to our customer. For cardinality=many
scenarios, each event points to the common metadata of all the events.
So when using metadata field when cardinality=many, it only needs to
take one of the events to get all the data (e.g. events[0].metadata).
Returns:
--------
typing.Mapping[str, object]
Return the Python dictionary of trigger metadata
"""
if self.__trigger_metadata is None:
return None

if self._trigger_metadata_pyobj is None:
self._trigger_metadata_pyobj = {
k: v.python_value for (k, v) in self.__trigger_metadata.items()
}
return self._trigger_metadata_pyobj

def __repr__(self) -> str:
return (
f'<azure.EventHubEvent '
Expand Down
3 changes: 3 additions & 0 deletions azure/functions/_http.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

import collections.abc
import io
import json
Expand Down
3 changes: 3 additions & 0 deletions azure/functions/_http_wsgi.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

from typing import Callable, Dict, List, Optional, Any
from io import BytesIO, StringIO
from os import linesep
Expand Down
37 changes: 37 additions & 0 deletions azure/functions/_kafka.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

import abc
import typing


class AbstractKafkaEvent(abc.ABC):

@abc.abstractmethod
def get_body(self) -> bytes:
pass

@property
@abc.abstractmethod
def key(self) -> typing.Optional[str]:
pass

@property
@abc.abstractmethod
def offset(self) -> typing.Optional[int]:
pass

@property
@abc.abstractmethod
def partition(self) -> typing.Optional[int]:
pass

@property
@abc.abstractmethod
def topic(self) -> typing.Optional[str]:
pass

@property
@abc.abstractmethod
def timestamp(self) -> typing.Optional[str]:
pass
3 changes: 3 additions & 0 deletions azure/functions/_queue.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

import datetime
import json
import typing
Expand Down
8 changes: 8 additions & 0 deletions azure/functions/_servicebus.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

import abc
import datetime
Expand Down Expand Up @@ -94,3 +96,9 @@ def to(self) -> typing.Optional[str]:
def user_properties(self) -> typing.Dict[str, object]:
"""User-defined message metadata."""
pass

@property
@abc.abstractmethod
def metadata(self) -> typing.Optional[typing.Mapping[str, typing.Any]]:
"""The serialized JSON string from trigger metadata"""
pass
2 changes: 1 addition & 1 deletion azure/functions/_thirdparty/typing_inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ def get_args(tp, evaluate=None):
get_args(Callable[[], T][int], evaluate=True) == ([], int,)
"""
if NEW_TYPING:
if evaluate is not None and not evaluate:
if not (evaluate is None or evaluate):
raise ValueError('evaluate can only be True in Python 3.7')
if isinstance(tp, _GenericAlias):
res = tp.__args__
Expand Down
3 changes: 3 additions & 0 deletions azure/functions/_utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

from typing import List, Tuple, Optional
from datetime import datetime

Expand Down
8 changes: 4 additions & 4 deletions azure/functions/blob.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

import io
from typing import Optional, Union, Any

Expand Down Expand Up @@ -94,10 +97,7 @@ def decode(cls, data: meta.Datum, *, trigger_metadata) -> Any:
trigger_metadata, 'Properties', python_type=dict)
if properties:
length = properties.get('Length')
if length:
length = int(length)
else:
length = None
length = int(length) if length else None
else:
length = None

Expand Down
Loading

0 comments on commit 01075c7

Please sign in to comment.