Skip to content

Commit 01075c7

Browse files
author
Hanzhang Zeng (Roger)
committed
Merge branch 'release/1.3.0'
2 parents ac94476 + 633acd8 commit 01075c7

40 files changed

+1197
-88
lines changed

README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
<img src="https://raw.githubusercontent.com/Azure/azure-functions-python-worker/dev/docs/Azure.Functions.svg" width = "180" alt="Functions Header Image">
2+
3+
|Branch|Status|Coverage|
4+
|---|---|---|
5+
|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)
6+
|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)
7+
8+
# Overview
9+
10+
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.
11+
12+
Here is the current status of Python in Azure Functions:
13+
14+
What's available?
15+
16+
- Build, test, debug and publish using Azure Functions Core Tools (CLI) or Visual Studio Code
17+
- Triggers / Bindings : HTTP, Blob, Queue, Timer, Cosmos DB, Event Grid, Event Hubs and Service Bus
18+
- Create a Python Function on Linux using a custom docker image
19+
- Triggers / Bindings : Custom binding support
120

221
# Contributing
322

azure-pipelines.yml

Lines changed: 46 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,49 @@
11
trigger:
2-
- master
3-
- dev
2+
- master
3+
- dev
4+
5+
schedules:
6+
- cron: "0 8 * * 1,3,5"
7+
displayName: Monday, Wednesday and Friday - 1 AM (PDT) build
8+
branches:
9+
include:
10+
- dev
11+
- master
12+
exclude:
13+
- release/*
14+
- releases/ancient/*
415

516
jobs:
6-
- job: Tests
7-
pool:
8-
vmImage: 'ubuntu-16.04'
9-
strategy:
10-
matrix:
11-
Python36:
12-
pythonVersion: '3.6'
13-
Python37:
14-
pythonVersion: '3.7'
15-
Python38:
16-
pythonVersion: '3.8'
17-
maxParallel: 3
18-
steps:
19-
- task: UsePythonVersion@0
20-
inputs:
21-
versionSpec: '$(pythonVersion)'
22-
addToPath: true
23-
- task: ShellScript@2
24-
inputs:
25-
disableAutoCwd: true
26-
scriptPath: .ci/build.sh
27-
displayName: 'Build'
28-
- bash: |
29-
chmod +x .ci/run_tests.sh
30-
.ci/run_tests.sh
31-
displayName: 'Run Tests'
32-
- task: PublishCodeCoverageResults@1
33-
inputs:
34-
codeCoverageTool: cobertura
35-
summaryFileLocation: coverage.xml
36-
- bash: |
37-
rm coverage.xml
38-
displayName: 'Clearing coverage.xml file'
17+
- job: Tests
18+
pool:
19+
vmImage: 'ubuntu-16.04'
20+
strategy:
21+
matrix:
22+
Python36:
23+
pythonVersion: '3.6'
24+
Python37:
25+
pythonVersion: '3.7'
26+
Python38:
27+
pythonVersion: '3.8'
28+
maxParallel: 3
29+
steps:
30+
- task: UsePythonVersion@0
31+
inputs:
32+
versionSpec: '$(pythonVersion)'
33+
addToPath: true
34+
- task: ShellScript@2
35+
inputs:
36+
disableAutoCwd: true
37+
scriptPath: .ci/build.sh
38+
displayName: 'Build'
39+
- bash: |
40+
chmod +x .ci/run_tests.sh
41+
.ci/run_tests.sh
42+
displayName: 'Run Tests'
43+
- task: PublishCodeCoverageResults@1
44+
inputs:
45+
codeCoverageTool: cobertura
46+
summaryFileLocation: coverage.xml
47+
- bash: |
48+
rm coverage.xml
49+
displayName: 'Clearing coverage.xml file'

azure/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# Copyright (c) Microsoft Corporation. All rights reserved.
2+
# Licensed under the MIT License.
3+
14
from pkgutil import extend_path
25
import typing
6+
37
__path__: typing.Iterable[str] = extend_path(__path__, __name__)

azure/functions/__init__.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
1+
# Copyright (c) Microsoft Corporation. All rights reserved.
2+
# Licensed under the MIT License.
3+
14
from ._abc import TimerRequest, InputStream, Context, Out # NoQA
25
from ._eventhub import EventHubEvent # NoQA
36
from ._eventgrid import EventGridEvent, EventGridOutputEvent # NoQA
47
from ._cosmosdb import Document, DocumentList # NoQA
58
from ._http import HttpRequest # NoQA
69
from ._http import HttpResponse # NoQA
710
from ._http_wsgi import WsgiMiddleware # NoQA
11+
from .kafka import KafkaEvent, KafkaConverter, KafkaTriggerConverter # NoQA
812
from ._queue import QueueMessage # NoQA
913
from ._servicebus import ServiceBusMessage # NoQA
1014
from ._durable_functions import OrchestrationContext # NoQA
1115
from .meta import get_binding_registry # NoQA
16+
1217
# Import binding implementations to register them
1318
from . import blob # NoQA
1419
from . import cosmosdb # NoQA
1520
from . import eventgrid # NoQA
1621
from . import eventhub # NoQA
1722
from . import http # NoQA
23+
from . import kafka # NoQA
1824
from . import queue # NoQA
1925
from . import servicebus # NoQA
2026
from . import timer # NoQA
@@ -37,6 +43,9 @@
3743
'HttpRequest',
3844
'HttpResponse',
3945
'InputStream',
46+
'KafkaEvent',
47+
'KafkaConverter',
48+
'KafkaTriggerConverter',
4049
'OrchestrationContext',
4150
'QueueMessage',
4251
'ServiceBusMessage',
@@ -46,4 +55,4 @@
4655
'WsgiMiddleware'
4756
)
4857

49-
__version__ = '1.2.1'
58+
__version__ = '1.3.0'

azure/functions/_abc.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# Copyright (c) Microsoft Corporation. All rights reserved.
2+
# Licensed under the MIT License.
3+
14
import abc
25
import datetime
36
import io

azure/functions/_cosmosdb.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# Copyright (c) Microsoft Corporation. All rights reserved.
2+
# Licensed under the MIT License.
3+
14
import collections
25
import json
36

azure/functions/_durable_functions.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# Copyright (c) Microsoft Corporation. All rights reserved.
2+
# Licensed under the MIT License.
3+
14
from typing import Union
25
from . import _abc
36
from importlib import import_module
@@ -33,12 +36,11 @@ def _serialize_custom_object(obj):
3336
"function")
3437
# Encode to json using the object's `to_json`
3538
obj_type = type(obj)
36-
dict_obj = {
39+
return {
3740
"__class__": obj.__class__.__name__,
3841
"__module__": obj.__module__,
3942
"__data__": obj_type.to_json(obj)
4043
}
41-
return dict_obj
4244

4345

4446
def _deserialize_custom_object(obj: dict) -> object:

azure/functions/_eventgrid.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# Copyright (c) Microsoft Corporation. All rights reserved.
2+
# Licensed under the MIT License.
3+
14
import datetime
25
import typing
36

azure/functions/_eventhub.py

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,37 @@
1+
# Copyright (c) Microsoft Corporation. All rights reserved.
2+
# Licensed under the MIT License.
3+
14
import datetime
25
import typing
36

4-
from azure.functions import _abc as funcabc
7+
from azure.functions import _abc as func_abc
8+
from azure.functions import meta
59

610

7-
class EventHubEvent(funcabc.EventHubEvent):
11+
class EventHubEvent(func_abc.EventHubEvent):
812
"""A concrete implementation of Event Hub message type."""
913

1014
def __init__(self, *,
1115
body: bytes,
16+
trigger_metadata: typing.Mapping[str, meta.Datum] = None,
1217
enqueued_time: typing.Optional[datetime.datetime] = None,
1318
partition_key: typing.Optional[str] = None,
1419
sequence_number: typing.Optional[int] = None,
1520
offset: typing.Optional[str] = None,
1621
iothub_metadata: typing.Optional[
1722
typing.Mapping[str, str]] = None) -> None:
1823
self.__body = body
24+
self.__trigger_metadata = trigger_metadata
1925
self.__enqueued_time = enqueued_time
2026
self.__partition_key = partition_key
2127
self.__sequence_number = sequence_number
2228
self.__offset = offset
2329
self.__iothub_metadata = iothub_metadata
2430

31+
# Cache for trigger metadata after Python object conversion
32+
self._trigger_metadata_pyobj: typing.Optional[
33+
typing.Mapping[str, typing.Any]] = None
34+
2535
def get_body(self) -> bytes:
2636
return self.__body
2737

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

58+
@property
59+
def metadata(self) -> typing.Optional[typing.Mapping[str, typing.Any]]:
60+
"""Getting read-only trigger metadata in a Python dictionary.
61+
62+
Exposing the raw trigger_metadata to our customer. For cardinality=many
63+
scenarios, each event points to the common metadata of all the events.
64+
65+
So when using metadata field when cardinality=many, it only needs to
66+
take one of the events to get all the data (e.g. events[0].metadata).
67+
68+
Returns:
69+
--------
70+
typing.Mapping[str, object]
71+
Return the Python dictionary of trigger metadata
72+
"""
73+
if self.__trigger_metadata is None:
74+
return None
75+
76+
if self._trigger_metadata_pyobj is None:
77+
self._trigger_metadata_pyobj = {
78+
k: v.python_value for (k, v) in self.__trigger_metadata.items()
79+
}
80+
return self._trigger_metadata_pyobj
81+
4882
def __repr__(self) -> str:
4983
return (
5084
f'<azure.EventHubEvent '

azure/functions/_http.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# Copyright (c) Microsoft Corporation. All rights reserved.
2+
# Licensed under the MIT License.
3+
14
import collections.abc
25
import io
36
import json

0 commit comments

Comments
 (0)