Skip to content

Commit

Permalink
Merge branch 'dev' into patch-1
Browse files Browse the repository at this point in the history
  • Loading branch information
ashleysommer authored Dec 19, 2024
2 parents fe992e9 + 773c401 commit c1cfed6
Show file tree
Hide file tree
Showing 40 changed files with 674 additions and 9,195 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/label.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: "Pull Request Labeler"
on:
pull_request:
pull_request_target:
paths:
- '**/__init__.py'
jobs:
Expand Down
2 changes: 1 addition & 1 deletion CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@
# For all file changes, github would automatically include the following people in the PRs.
#

* @vrdmr @gavin-aguiar @YunchuWang @pdthummar @hallvictoria
* @vrdmr @gavin-aguiar @hallvictoria
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@

## 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](https://learn.microsoft.com/azure/azure-functions/functions-versions?#retired-versions)), 3.x ([EOL](https://learn.microsoft.com/azure/azure-functions/functions-versions?#retired-versions)) and 4.0 runtime.
Python support for Azure Functions is based on Python 3.8, 3.9, 3.10, 3.11, and 3.12 serverless hosting on Linux, and the Functions 2.x ([EOL](https://learn.microsoft.com/azure/azure-functions/functions-versions?#retired-versions)), 3.x ([EOL](https://learn.microsoft.com/azure/azure-functions/functions-versions?#retired-versions)) 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](https://learn.microsoft.com/azure/azure-functions/migrate-version-3-version-4)|[EOL](https://learn.microsoft.com/azure/azure-functions/migrate-version-3-version-4)|[EOL](https://learn.microsoft.com/azure/azure-functions/migrate-version-3-version-4)| [EOL](https://learn.microsoft.com/azure/azure-functions/migrate-version-3-version-4)| - |- |
| Azure Functions 4.0 | [EOL](https://azure.microsoft.com/en-au/updates/azure-functions-support-for-python-36-is-ending-on-30-september-2022/) | ✓ | ✓ | ✓ | ✓ | ✓ |
| Azure Functions Runtime | Python 3.8 | Python 3.9 | Python 3.10 | Python 3.11 | Python 3.12 |
|-------------------------|--------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------|-------------|-------------|-------------|
| Azure Functions 3.0 | [EOL](https://learn.microsoft.com/azure/azure-functions/migrate-version-3-version-4) | [EOL](https://learn.microsoft.com/azure/azure-functions/migrate-version-3-version-4) | - | - | - |
| Azure Functions 4.0 | ✓ | ✓ | ✓ | ✓ | ✓ |

_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
- Triggers / Bindings : Blob, Cosmos DB, Event Grid, Event Hub, HTTP, Kafka, MySQL, Queue, ServiceBus, SQL, Timer, and Warmup
- Create a Python Function on Linux using a custom docker image
- Triggers / Bindings : Custom binding support

Expand Down
6 changes: 5 additions & 1 deletion azure/functions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from ._queue import QueueMessage
from ._servicebus import ServiceBusMessage
from ._sql import SqlRow, SqlRowList
from ._mysql import MySqlRow, MySqlRowList

# Import binding implementations to register them
from . import blob # NoQA
Expand All @@ -37,6 +38,7 @@
from . import durable_functions # NoQA
from . import sql # NoQA
from . import warmup # NoQA
from . import mysql # NoQA


__all__ = (
Expand Down Expand Up @@ -67,6 +69,8 @@
'SqlRowList',
'TimerRequest',
'WarmUpContext',
'MySqlRow',
'MySqlRowList',

# Middlewares
'WsgiMiddleware',
Expand Down Expand Up @@ -98,4 +102,4 @@
'BlobSource'
)

__version__ = '1.21.0b3'
__version__ = '1.23.0b1'
2 changes: 1 addition & 1 deletion azure/functions/_abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import threading
import typing

from azure.functions._thirdparty.werkzeug.datastructures import Headers
from werkzeug.datastructures import Headers

T = typing.TypeVar('T')

Expand Down
22 changes: 10 additions & 12 deletions azure/functions/_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
import types
import typing

from werkzeug import formparser as _wk_parser
from werkzeug import http as _wk_http
from werkzeug.datastructures import (Headers, FileStorage, MultiDict,
ImmutableMultiDict)

from . import _abc
from ._thirdparty.werkzeug import datastructures as _wk_datastructures
from ._thirdparty.werkzeug import formparser as _wk_parser
from ._thirdparty.werkzeug import http as _wk_http
from ._thirdparty.werkzeug.datastructures import Headers


class BaseHeaders(collections.abc.Mapping):
Expand Down Expand Up @@ -174,8 +175,8 @@ def __init__(self,
self.__route_params = types.MappingProxyType(route_params or {})
self.__body_bytes = body
self.__form_parsed = False
self.__form = None
self.__files = None
self.__form: MultiDict[str, str]
self.__files: MultiDict[str, FileStorage]

@property
def url(self):
Expand Down Expand Up @@ -222,12 +223,9 @@ def _parse_form_data(self):
content_length = len(body)
mimetype, options = _wk_http.parse_options_header(content_type)
parser = _wk_parser.FormDataParser(
_wk_parser.default_stream_factory,
options.get('charset') or 'utf-8',
'replace',
None,
None,
_wk_datastructures.ImmutableMultiDict,
_wk_parser.default_stream_factory, max_form_memory_size=None,
max_content_length=None,
cls=ImmutableMultiDict
)

body_stream = io.BytesIO(body)
Expand Down
9 changes: 6 additions & 3 deletions azure/functions/_http_wsgi.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from typing import Dict, List, Optional, Any
import logging
from io import BytesIO, StringIO
from os import linesep
from typing import Dict, List, Optional, Any
from urllib.parse import ParseResult, urlparse, unquote_to_bytes
from wsgiref.headers import Headers

from ._abc import Context
from ._http import HttpRequest, HttpResponse
from ._thirdparty.werkzeug._compat import string_types, wsgi_encoding_dance


def wsgi_encoding_dance(value):
return value.encode().decode("latin1")


class WsgiRequest:
Expand Down Expand Up @@ -98,7 +101,7 @@ def to_environ(self, errors_buffer: StringIO) -> Dict[str, Any]:

# Ensure WSGI string fits in IOS-8859-1 code points
for k, v in environ.items():
if isinstance(v, string_types):
if isinstance(v, (str,)):
environ[k] = wsgi_encoding_dance(v)

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


class BaseMySqlRow(abc.ABC):

@classmethod
@abc.abstractmethod
def from_json(cls, json_data: str) -> 'BaseMySqlRow':
raise NotImplementedError

@classmethod
@abc.abstractmethod
def from_dict(cls, dct: dict) -> 'BaseMySqlRow':
raise NotImplementedError

@abc.abstractmethod
def __getitem__(self, key):
raise NotImplementedError

@abc.abstractmethod
def __setitem__(self, key, value):
raise NotImplementedError

@abc.abstractmethod
def to_json(self) -> str:
raise NotImplementedError


class BaseMySqlRowList(abc.ABC):
pass


class MySqlRow(BaseMySqlRow, collections.UserDict):
"""A MySql Row.
MySqlRow objects are ''UserDict'' subclasses and behave like dicts.
"""

@classmethod
def from_json(cls, json_data: str) -> 'BaseMySqlRow':
"""Create a MySqlRow from a JSON string."""
return cls.from_dict(json.loads(json_data))

@classmethod
def from_dict(cls, dct: dict) -> 'BaseMySqlRow':
"""Create a MySqlRow from a dict object"""
return cls({k: v for k, v in dct.items()})

def to_json(self) -> str:
"""Return the JSON representation of the MySqlRow"""
return json.dumps(dict(self))

def __getitem__(self, key):
return collections.UserDict.__getitem__(self, key)

def __setitem__(self, key, value):
return collections.UserDict.__setitem__(self, key, value)

def __repr__(self) -> str:
return (
f'<MySqlRow at 0x{id(self):0x}>'
)


class MySqlRowList(BaseMySqlRowList, collections.UserList):
"A ''UserList'' subclass containing a list of :class:'~MySqlRow' objects"
pass
17 changes: 10 additions & 7 deletions azure/functions/_servicebus.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ def correlation_id(self) -> Optional[str]:

@property
def dead_letter_error_description(self) -> Optional[str]:
"""Optionally describes the dead letter error description for the message.
"""Optionally describes the dead letter error description
for the message.
Returns:
--------
Expand All @@ -87,7 +88,8 @@ def dead_letter_error_description(self) -> Optional[str]:

@property
def dead_letter_reason(self) -> Optional[str]:
"""Optionally describes the dead letter reason description for the message.
"""Optionally describes the dead letter reason description
for the message.
Returns:
--------
Expand Down Expand Up @@ -404,11 +406,12 @@ def to(self) -> Optional[str]:

@property
def transaction_partition_key(self) -> Optional[str]:
"""If a message is sent via a transfer queue in the scope of a transaction,
this value selects the transfer queue partition: This is functionally
equivalent to PartitionKey and ensures that messages are kept together
and in order as they are transferred. Optionally describes the
partition key. Maximum length is 128 characters.
"""If a message is sent via a transfer queue in the scope of a
transaction, this value selects the transfer queue partition:
This is functionally equivalent to PartitionKey and ensures
that messages are kept together and in order as they are
transferred. Optionally describes the partition key. Maximum
length is 128 characters.
Returns:
--------
Expand Down
28 changes: 0 additions & 28 deletions azure/functions/_thirdparty/werkzeug/LICENSE.rst

This file was deleted.

Empty file.
Loading

0 comments on commit c1cfed6

Please sign in to comment.