Sample files for v2 programming model (#1312)

This commit is contained in:
Naren Soni 2023-03-14 14:25:03 -07:00 коммит произвёл Katy Shimizu
Родитель b9c124c468
Коммит f53ee92435
12 изменённых файлов: 846 добавлений и 0 удалений

95
Docs/action-schemas.json Normal file
Просмотреть файл

@ -0,0 +1,95 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "<ACTION_SCHEMA_URL>",
"title": "Actions",
"description": "An action used in Azure Functions' templates v2 template.json",
"type": "object",
"properties": {
"name": {
"description": "The arbitrary identifier for an action",
"type": "string"
},
"type": {
"description": "Type of the action",
"enum": [
"AppendToFile",
"ReadFromFile",
"ReplaceTokensInText",
"ShowMarkdownPreview",
"UserInput",
"WriteToFile"
]
},
"continueOnError": {
"description": "Whether to continue job execution if the action errors",
"type": "boolean"
},
"errorText": {
"description": "Text to display on error (ex. manual instructions)",
"type": "string"
},
"assignTo": {
"description": "Identifier to assign the action's output to",
"type": "string",
"pattern": "\\$\\([A-Z0-9_]+\\)"
},
"filePath": {
"description": "File path target of the action's operation",
"type": "string"
},
"source": {
"description": "Identifier of the input data for the action",
"type": "string",
"pattern": "\\$\\([A-Z0-9_]+\\)"
}
},
"required": [ "name", "type" ],
"allOf": [
{
"if": { "properties": { "type": { "const": "AppendToFile" } } },
"then": {
"properties": {
"createIfNotExists": {
"description": "If a file doesn't exist at filePath, create it",
"type": "boolean"
}
},
"required": [ "createIfNotExists", "filePath", "source" ]
}
},
{
"if": { "properties": { "type": { "const": "ReadFromFile" } } },
"then": { "required": [ "assignTo", "filePath" ] }
},
{
"if": { "properties": { "type": { "const": "ReplaceTokensInText" } } },
"then": { "required": [ "assignTo", "source" ] }
},
{
"if": { "properties": { "type": { "const": "ShowMarkdownPreview" } } },
"then": { "required": [ "filePath" ] }
},
{
"if": { "properties": { "type": { "const": "UserInput" } } },
"then": {
"properties": {
"paramId": {
"description": "Type data for the input corresponding to an entry in user-prompts.json",
"type": "string",
"pattern": "([a-zA-Z]+)-([a-zA-Z]+)"
},
"defaultValue": {
"description": "The default value to use if the user provides none",
"type": "string"
}
},
"required": [ "assignTo", "paramId" ]
}
},
{
"if": { "properties": { "type": { "const": "WriteToFile" } } },
"then": { "required": [ "filePath", "source" ] }
}
]
}

Просмотреть файл

@ -0,0 +1,47 @@
{
"author": "Katy Shimizu", // Primary contact for this template (author/maintainer/owner/etc).
// TODO: Is "name" a display name or just a human readable tag? If display name, shouldn't it be a resx pointer?
"name": "<Trigger> Name", // If a resx pointer (ex. $Trigger_name), could be displayed in UI.
"description": "$Trigger_description", // Resx pointer to localized short description of trigger functionality.
"programmingModel": "v2", // "v1" | "v2". v1 = legacy; v2 = Stein.
"language": "python", // Programming language. ex. python, dotnet, node, powershell.
"jobs": [ // Each 'job' is a collection of actions associated with a command or 'flow.'
{
"name": "Human-Readable Trigger Flow Name", // If a resx pointer (ex. $Trigger_Flow_name), could be displayed in UI.
"condition": { // Job-level condition; ex. to determine whether to enable it as an option.
"name": "SHOW_V2_TEMPLATES", // Variable name - for example, an environment variable.
"expectedValue": "true" // Variable value for which this condition is true.
},
"input": {
// TODO: note on who defines userCommand values - template creators?
"userCommand": "createNewApp", // Value tooling can match on to filter which job(s) to run for a flow.
"assignTo": "$(APP_FILENAME)" // Key for initial input value. Actions can prompt for further inputs, ex. binding settings.
// ex. in the append scenario, this could be 'function_app.py' or the selected file
},
"actions": [ // Keys for action definitions (full action definitions below).
"getBindingParamValue", // NOTE: List actions in order of operation.
"readFileContent",
"replaceTextInFile",
"writeFile",
"showMarkdownPreview"
]
},
],
"actions": [ // Full action definitions. An action can be used by more than one job.
{
// TODO: Change 'name' to 'key'?
// Common Action Properties
"name": "getBindingParamValue", // Arbitrary value for lookup from job(s).
"type": "UserInput", // Corresponds to entry in actions_schema.json.
"condition": { // Action-level condition. If undefined, action always runs.
"name": "SOME_FLAG",
"expectedValue": "true"
},
"continueOnError": "false", // Whether to continue job execution on error.
"errorText": "$Trigger_param_error", // Resx pointer; text to show user on error. ex. manual instructions.
// Action Type Specific Properties
"property_one": "foo", // These vary by the specific action type. See actions_schema.json for examples.
"property_two": "bar"
}
]
}

87
Docs/template-schema.json Normal file
Просмотреть файл

@ -0,0 +1,87 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "<TEMPLATE_SCHEMA_URL>",
"title": "Azure Functions Template",
"description": "A template in Azure Functions' v2 template schema",
"type": "object",
"properties": {
"author": {
"description": "The author of this template (author/maintainer/owner/contact)",
"type": "string"
},
"name": {
"description": "The name of this template; usually <Trigger> ex. 'HTTP Trigger'",
"type": "string"
},
"description": {
"description": "A short description of this template's trigger's functionality",
"type": "string"
},
"programmingModel": {
"description": "The programming model the template applies to",
"enum": [ "v1", "v2" ]
},
"language": {
"description": "The programming language the template applies to",
"enum": [ "dotnet", "node", "python", "powershell" ]
},
"jobs": {
"description": "The list of jobs defined by the template, each corresponding to a user gesture",
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"description": "The display name of this job",
"type": "string"
},
"condition": {
"description": "The condition that must evaluate to true to run this job",
"name": {
"description": "The name of the variable to evaluate",
"type": "string"
},
"expectedValue": {
"description": "The value for which the condition is true",
"type": "string"
}
},
"input": {
"description": "The input provided to the job by the user gesture in the tooling",
"userCommand": {
"description": "The identifier for a job",
"type": "string"
},
"assignTo": {
"description": "Identifier to assign initial tooling-provided input to",
"type": "string",
"pattern": "\\$\\([A-Z0-9_]+\\"
}
},
"actions": {
"description": "Names of the actions the job executes in order of operation",
"items": {
"oneOf": [
{ "type": "string" },
{ "$ref": "<ACTION_SCHEMA_URL>" }
],
"minItems": 1
}
},
"required": [ "name", "input", "actions" ]
},
"minItems": 1,
"uniqueItems": true
}
},
"actions": {
"description": "The list of action definitions used by jobs defined by a template",
"type": "array",
"items": { "$ref": "<ACTION_SCHEMA_URL>" },
"minItems": 1,
"uniqueItems": true
}
},
"required": [ "author", "name", "description", "programmingModel", "language", "jobs", "actions" ]
}

Просмотреть файл

@ -0,0 +1,244 @@
[
{
"name": "httpTrigger-route",
"type": "string",
"label": "$httpTrigger_route_label",
"help": "$httpTrigger_route_help"
},
{
"name": "trigger-functionName",
"type": "string",
"label": "Provide a function name",
"help": "Name of the function you want to",
"validators": [
{
"expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
"errorText": "[variables('parameterName')]"
}
]
},
{
"name": "httpTrigger-authLevel",
"value": "enum",
"defaultValue": "function",
"enum": [
{
"value": "function",
"display": "Function"
},
{
"value": "anonymous",
"display": "Anonymous"
},
{
"value": "admin",
"display": "Admin"
}
],
"label": "$httpTrigger_authLevel_label",
"help": "$httpTrigger_authLevel_help"
},
{
"name": "timerTrigger-schedule",
"value": "string",
"defaultValue": "0 * * * * *",
"label": "$timerTrigger_schedule_label",
"help": "$timerTrigger_schedule_help",
"validators": [
{
"expression": "^(\\*|((([1-5]\\d)|\\d)(\\-(([1-5]\\d)|\\d)(\\/\\d+)?)?)(,((([1-5]\\d)|\\d)(\\-(([1-5]\\d)|\\d)(\\/\\d+)?)?))*)(\\/\\d+)? (\\*|((([1-5]\\d)|\\d)(\\-(([1-5]\\d)|\\d)(\\/\\d+)?)?)(,((([1-5]\\d)|\\d)(\\-(([1-5]\\d)|\\d)(\\/\\d+)?)?))*)(\\/\\d+)? (\\*|(((1\\d)|(2[0-3])|\\d)(\\-((1\\d)|(2[0-3])|\\d)(\\/\\d+)?)?)(,(((1\\d)|(2[0-3])|\\d)(\\-((1\\d)|(2[0-3])|\\d)(\\/\\d+)?)?))*)(\\/\\d+)? (\\*|((([1-2]\\d)|(3[0-1])|[1-9])(\\-(([1-2]\\d)|(3[0-1])|[1-9])(\\/\\d+)?)?)(,((([1-2]\\d)|(3[0-1])|[1-9])(\\-(([1-2]\\d)|(3[0-1])|[1-9])(\\/\\d+)?)?))*)(\\/\\d+)? (\\*|(([A-Za-z]+|(1[0-2])|[1-9])(\\-([A-Za-z]+|(1[0-2])|[1-9])(\\/\\d+)?)?)(,(([A-Za-z]+|(1[0-2])|[1-9])(\\-([A-Za-z]+|(1[0-2])|[1-9])(\\/\\d+)?)?))*)(\\/\\d+)? (\\*|(([A-Za-z]+|[0-6])(\\-([A-Za-z]+|[0-6])(\\/\\d+)?)?)(,(([A-Za-z]+|[0-6])(\\-([A-Za-z]+|[0-6])(\\/\\d+)?)?))*)(\\/\\d+)?$",
"errorText": "$timerTrigger_schedule_errorText"
}
]
},
{
"name": "queueTrigger-queueName",
"value": "string",
"defaultValue": "myqueue",
"label": "$queueTrigger_queueName_label",
"help": "$queueTrigger_queueName_help",
"validators": [
{
"expression": "^[0-9a-z][a-z0-9-]{1,61}[0-9a-z]$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
"errorText": "$queueTrigger_queueName_errorText"
}
]
},
{
"name": "queueTrigger-connection",
"value": "string",
"resource": "Storage",
"label": "$variables_storageConnStringLabel",
"help": "$variables_appSettingsHelp"
},
{
"name": "blobTrigger-path",
"value": "string",
"defaultValue": "mycontainer",
"label": "$blobTrigger_path_label",
"help": "$blobTrigger_path_help",
"validators": [
{
"expression": "(((^[a-z0-9](?:[a-z0-9]|(?:\\-(?!\\-))){1,61}[a-z0-9])|(^[{][a-zA-Z0-9]{1,126}[}])|(^[%][a-zA-Z0-9]{1,126}[%]))[\\/](\\S){0,1023}[^\\/]$)|(((^[a-z0-9](?:[a-z0-9]|(?:\\-(?!\\-))){1,61}[a-z0-9]$)|(^[{][a-zA-Z0-9]{1,126}[}]$)|(^[%][a-zA-Z0-9]{1,126}[%]$)))",
"errorText": "$blobTrigger_path_errorText"
}
]
},
{
"name": "blobTrigger-connection",
"value": "string",
"label": "$blobTrigger_path_label",
"help": "$blobTrigger_path_help"
},
{
"name": "cosmosDBTrigger-connectionStringSetting",
"value": "string",
"resource": "DocumentDB",
"label": "$cosmosDBIn_connection_label",
"help": "$cosmosDBIn_connection_help",
"placeholder": "$variables_selectConnection"
},
{
"name": "cosmosDBTrigger-databaseName",
"value": "string",
"defaultValue": "",
"label": "$cosmosDBIn_databaseName_label",
"help": "$cosmosDBIn_databaseName_help"
},
{
"name": "cosmosDBTrigger-collectionName",
"value": "string",
"defaultValue": "",
"label": "$cosmosDBIn_collectionName_label",
"help": "$cosmosDBIn_collectionName_help"
},
{
"name": "cosmosDBTrigger-leaseCollectionName",
"value": "string",
"label": "$cosmosDBIn_leaseCollectionName_label",
"help": "$cosmosDBIn_leaseCollectionName_help"
},
{
"name": "cosmosDBTrigger-createLeaseCollectionIfNotExists",
"value": "boolean",
"defaultValue": true,
"label": "$cosmosDBIn_createIfNotExists_label",
"help": "$cosmosDBIn_createIfNotExists_help"
},
{
"name": "eventHubTrigger-connection",
"value": "string",
"resource": "EventHub",
"label": "$eventHubTrigger_connection_label",
"help": "$eventHubTrigger_connection_help",
"placeholder": "$variables_selectConnection"
},
{
"name": "eventHubTrigger-eventHubName",
"value": "string",
"defaultValue": "myeventhub",
"label": "$eventHubOut_path_label",
"help": "$eventHubTrigger_path_help",
"validators": [
{
"expression": "^[a-zA-Z0-9]$|^[a-zA-Z0-9][a-zA-Z0-9-_.]{0,48}[a-zA-Z0-9]$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
"errorText": "$eventHubTrigger_path_errorText"
}
]
},
{
"name": "eventHubTrigger-consumerGroup",
"value": "string",
"defaultValue": "$Default",
"label": "$eventHubTrigger_consumerGroup_label",
"help": "$eventHubTrigger_consumerGroup_help",
"validators": [
{
"expression": "(^[a-zA-Z0-9]$|^[a-zA-Z0-9][a-zA-Z0-9-_.]{0,48}[a-zA-Z0-9]$)|^\\$Default$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
"errorText": "$eventHubTrigger_consumerGroup_errorText"
}
]
},
{
"name": "eventHubTrigger-cardinality",
"value": "enum",
"defaultValue": "many",
"enum": [
{
"value": "one",
"display": "One"
},
{
"value": "many",
"display": "Many"
}
],
"label": "$eventHubTrigger_cardinality_label",
"help": "$eventHubTrigger_cardinality_help"
},
{
"name": "eventHubTrigger-dataType",
"value": "enum",
"enum": [
{
"value": "string",
"display": "String"
},
{
"value": "binary",
"display": "Binary"
},
{
"value": "stream",
"display": "Stream"
}
]
},
{
"name": "serviceBusTrigger-connection",
"value": "string",
"resource": "ServiceBus",
"label": "$serviceBusTrigger_connection_label",
"help": "$serviceBusTrigger_connection_help",
"placeholder": "[variables('selectConnection')]"
},
{
"name": "serviceBusTrigger-queueName",
"value": "string",
"defaultValue": "mysbqueue",
"label": "$serviceBusTrigger_queueName_label",
"help": "$serviceBusTrigger_queueName_help",
"validators": [
{
"expression": "^[a-zA-Z0-9]$|^[a-zA-Z0-9][a-zA-Z0-9-_.]{0,48}([a-zA-Z0-9]$|[a-zA-Z0-9][\\/]\\$DeadLetterQueue$)|^[{][a-zA-Z0-9]{1,126}([}]$|[}][\\/]\\$DeadLetterQueue$)|^[%][a-zA-Z0-9]{1,126}([%]$|[%][\\/]\\$DeadLetterQueue$)",
"errorText": "$serviceBusTrigger_queueName_errorText"
}
]
},
{
"name": "serviceBusTrigger-topicName",
"value": "string",
"defaultValue": "mysbtopic",
"label": "$serviceBusTrigger_topicName_label",
"help": "$serviceBusTrigger_topicName_help",
"validators": [
{
"expression": "^[a-zA-Z0-9]$|^[a-zA-Z0-9][a-zA-Z0-9-_.]{0,48}[a-zA-Z0-9]$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
"errorText": "$serviceBusTrigger_topicName_errorText"
}
]
},
{
"name": "serviceBusTrigger-subscriptionName",
"value": "string",
"defaultValue": "mysubscription",
"label": "$serviceBusTrigger_subscriptionName_label",
"help": "$serviceBusTrigger_subscriptionName_help",
"validators": [
{
"expression": "^[a-zA-Z0-9]$|^[a-zA-Z0-9][a-zA-Z0-9-_.]{0,48}([a-zA-Z0-9]$|[a-zA-Z0-9][\\/]\\$DeadLetterQueue$)|^[{][a-zA-Z0-9]{1,126}([}]$|[}][\\/]\\$DeadLetterQueue$)|^[%][a-zA-Z0-9]{1,126}([%]$|[%][\\/]\\$DeadLetterQueue$)",
"errorText": "$serviceBusTrigger_subscriptionName_errorText"
}
]
}
]

Просмотреть файл

@ -0,0 +1,26 @@
import azure.functions as func
import logging
app = func.FunctionApp(auth_level=func.AuthLevel.$(AUTHLEVEL_VALUE))
@app.function_name(name="$(FUNCTION_NAME_INPUT)")
@app.route(route="hello")
def $(FUNCTION_NAME_INPUT)(req: func.HttpRequest) -> func.HttpResponse:
logging.info('Python HTTP trigger function processed a request.')
name = req.params.get('name')
if not name:
try:
req_body = req.get_json()
except ValueError:
pass
else:
name = req_body.get('name')
if name:
return func.HttpResponse(f"Hello, {name}. This HTTP triggered function executed successfully.")
else:
return func.HttpResponse(
"This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.",
status_code=200
)

Просмотреть файл

@ -0,0 +1,21 @@
@app.function_name(name="$(FUNCTION_NAME_INPUT)")
@app.route(route="hello")
def $(FUNCTION_NAME_INPUT)(req: func.HttpRequest) -> func.HttpResponse:
logging.info('Python HTTP trigger function processed a request.')
name = req.params.get('name')
if not name:
try:
req_body = req.get_json()
except ValueError:
pass
else:
name = req_body.get('name')
if name:
return func.HttpResponse(f"Hello, {name}. This HTTP triggered function executed successfully.")
else:
return func.HttpResponse(
"This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.",
status_code=200
)

Просмотреть файл

@ -0,0 +1,56 @@
# Azure Functions: HTTP Trigger in Python
## HTTP Trigger
The HTTP trigger lets you invoke a function with an HTTP request. You can use an HTTP trigger to build serverless APIs and respond to webhooks.
## Using the Template
Following is an example code snippet for HTTP Trigger using the [Python programming model V2](https://aka.ms/pythonprogrammingmodel) (currently in Preview).
```python
import azure.functions as func
import logging
app = func.FunctionApp(auth_level=func.AuthLevel.ANONYMOUS)
@app.function_name(name="HttpTrigger1")
@app.route(route="hello")
def test_function(req: func.HttpRequest) -> func.HttpResponse:
logging.info('Python HTTP trigger function processed a request.')
name = req.params.get('name')
if not name:
try:
req_body = req.get_json()
except ValueError:
pass
else:
name = req_body.get('name')
if name:
return func.HttpResponse(f"Hello, {name}. This HTTP triggered function executed successfully.")
else:
return func.HttpResponse(
"This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.",
status_code=200
)
```
To run the code snippet generated through the command palette, note the following:
- The function application is defined and named `app`.
- Confirm that the parameters within the trigger reflect values that correspond with your storage account.
- The name of the file must be `function_app.py`.
Note that HTTP output bindings are also supported in Azure Functions. To learn more, see [Azure Functions HTTP triggers and bindings overview](https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-http-webhook?tabs=in-process%2Cfunctionsv2&pivots=programming-language-python)
## Programming Model V2 (Preview)
The new programming model in Azure Functions Python delivers an experience that aligns with Python development principles, and subsequently with commonly used Python frameworks.
The improved programming model requires fewer files than the default model, and specifically eliminates the need for a configuration file (`function.json`). Instead, triggers and bindings are represented in the `function_app.py` file as decorators. Moreover, functions can be logically organized with support for multiple functions to be stored in the same file. Functions within the same function application can also be stored in different files, and be referenced as blueprints.
To learn more about using the new Python programming model for Azure Functions, see the [Azure Functions Python developer guide](https://aka.ms/pythondeveloperguide). Note that in addition to the documentation, [hints](https://aka.ms/functions-python-hints) are available in code editors that support type checking with PYI files.
To learn more about the new programming model for Azure Functions in Python, see [Programming Models in Azure Functions](https://aka.ms/functions-programming-models).

Просмотреть файл

@ -0,0 +1,100 @@
{
"author": "Naren Soni",
"name": "HTTP trigger",
"description": "$HttpTrigger_description",
"programmingModel": "v2",
"language": "python",
"jobs": [
{
"name": "Create New Project with HttpTrigger function",
"input" : {
"userCommand" : "createNewApp",
"assignTo" : "$(APP_FILENAME)"
},
"actions": [
"getAuthValue",
"getFunctionName",
"readFileContent_FunctionApp",
"replaceTokensInText_FunctionApp",
"writeFile_FunctionApp",
"showMarkdownPreview"
]
},
{
"name": "Add httpTrigger function to an existing file",
"input" : {
"userCommand" : "appendToFile",
"assignTo" : "$(SELECTED_FILENAME)"
},
"actions": [
"getFunctionName",
"readFileContent_FunctionBody",
"replaceTokensInText_FunctionBody",
"appendFileContent_FunctionApp",
"showMarkdownPreview"
]
}
],
"actions" : [
{
"name": "getAuthValue",
"type": "UserInput",
"assignTo": "$(AUTHLEVEL_VALUE)",
"paramId": "httpTrigger-authLevel",
"defaultValue": "function"
},
{
"name": "getFunctionName",
"type": "UserInput",
"assignTo": "$(FUNCTION_NAME_INPUT)",
"paramId": "trigger-functionName",
"defaultValue": "HttpTrigger"
},
{
"name": "readFileContent_FunctionApp",
"type": "ReadFromFile",
"assignTo": "$(FUNCTION_APP)",
"filePath" : "function_app.py"
},
{
"name": "replaceTokensInText_FunctionApp",
"type": "ReplaceTokensInText",
"source": "$(FUNCTION_APP)",
"assignTo" : "$(FUNCTION_APP)"
},
{
"name": "writeFile_FunctionApp",
"type": "WriteToFile",
"source": "$(FUNCTION_APP)",
"filePath" : "$(APP_FILENAME)",
"continueOnError" : false,
"errorText" : "Unable to create the function app"
},
{
"name": "readFileContent_FunctionApp",
"type": "ReadFromFile",
"assignTo": "$(FUNCTION_BODY)",
"filePath" : "function_body.py"
},
{
"name": "replaceTokensInText_FunctionBody",
"type": "ReplaceTokensInText",
"source": "$(FUNCTION_BODY)",
"assignTo" : "$(FUNCTION_BODY)"
},
{
"name": "appendFileContent_FunctionApp",
"type": "AppendToFile",
"createIfNotExists" : false,
"source": "$(FUNCTION_BODY)",
"filePath" : "$(SELECTED_FILENAME)",
"continueOnError" : false,
"errorText" : "Unable to create httpTrigger function"
},
{
"name": "ShowMarkdownPreview",
"type": "ShowMarkdownPreview",
"filePath" : "http_trigger_template.md"
}
]
}

Просмотреть файл

@ -0,0 +1,9 @@
import datetime
import logging
import azure.functions as func
app = func.FunctionApp()
$(AppBody)

Просмотреть файл

@ -0,0 +1,11 @@
@app.function_name(name="$(FUNCTION_NAME_INPUT)")
@app.schedule(schedule="$(SCHEDULE_INPUT)", arg_name="mytimer", run_on_startup=True,
use_monitor=False)
def $(FUNCTION_NAME_INPUT)(myTimer: func.TimerRequest) -> None:
utc_timestamp = datetime.datetime.utcnow().replace(
tzinfo=datetime.timezone.utc).isoformat()
if myTimer.past_due:
logging.info('The timer is past due!')
logging.info('Python timer trigger function ran at %s', utc_timestamp)

Просмотреть файл

@ -0,0 +1,103 @@
{
"author": "kashimiz",
"name": "Timer Trigger",
"description": "$TimerTrigger_description",
"programmingModel": "v2",
"language": "python",
"jobs": [
{
"name": "Create New Project with Timer Function",
"input": {
"userCommand": "createNewApp",
"assignTo": "$(APP_FILENAME)"
},
"actions": [
"getScheduleValue",
"getFunctionName",
"readFileContent_FunctionBody",
"replaceText_FunctionBody",
"readFileContent_FunctionApp",
"replaceText_FunctionApp",
"writeFile_FunctionApp",
"showMarkdownPreview"
]
},
{
"name": "Append Timer Function to File",
"input": [
{
"userCommand": "appendToFile",
"assignTo": "$(SELECTED_FILENAME)"
}
],
"actions": [
"getScheduleValue",
"getFunctionNameAction",
"readFileContent_FunctionBody",
"replaceText_FunctionBody",
"appendFileContent_FunctionApp",
"showMarkdownPreview"
]
}
],
"actions": [
{
"name": "getScheduleValue",
"type": "UserInput",
"assignTo": "$(SCHEDULE_INPUT)",
"paramId": "timerTrigger-schedule",
"defaultValue": "0 5/* * * * *"
},
{
"name": "getFunctionName",
"type": "UserInput",
"assignTo": "$(FUNCTION_NAME_INPUT)",
"paramId": "trigger-functionName",
"defaultValue": "MyTimerFunction"
},
{
"name": "readFileContent_FunctionBody",
"type": "ReadFromFile",
"assignTo": "$(TIMER_FUNCTION_BODY)",
"filePath": "function_body.py"
},
{
"name": "replaceText_FunctionBody",
"type": "ReplaceTokensInText",
"assignTo": "$(TIMER_FUNCTION_BODY)",
"source": "$(TIMER_FUNCTION_BODY)"
},
{
"name": "readFileContent_FunctionApp",
"type": "ReadFromFile",
"assignTo": "$(FUNCTION_APP)",
"filePath": "function_app.py"
},
{
"name": "replaceText_FunctionApp",
"type": "ReplaceTokensInText",
"assignTo": "$(FUNCTION_APP_TRANSFORMED)",
"source": "$(FUNCTION_APP)"
},
{
"name": "writeFile_FunctionApp",
"type": "WriteToFile",
"filePath": "$(APP_FILENAME)",
"source": "$(FUNCTION_APP_TRANSFORMED)"
},
{
"name": "appendFileContent_FunctionApp",
"type": "AppendToFile",
"createIfNotExists" : false,
"source": "$(FUNCTION_APP_TRANSFORMED)",
"filePath" : "$(SELECTED_FILENAME)",
"continueOnError" : false,
"errorText" : "Unable to add template"
},
{
"name": "showMarkdownPreview",
"type": "ShowMarkdownPreview",
"filePath": "http_trigger_template.md"
}
]
}

Просмотреть файл

@ -0,0 +1,47 @@
# Azure Functions: Timer Trigger in Python
## Timer Trigger
A timer trigger lets you run a function on a schedule.
## Using the Template
Following is an example code snippet for Timer Trigger using the [Python programming model V2](https://aka.ms/pythonprogrammingmodel) (currently in Preview).
```python
import datetime
import logging
import azure.functions as func
app = func.FunctionApp()
@app.function_name(name="mytimer")
@app.schedule(schedule="0 */5 * * * *", arg_name="mytimer", run_on_startup=True,
use_monitor=False)
def test_function(mytimer: func.TimerRequest) -> None:
utc_timestamp = datetime.datetime.utcnow().replace(
tzinfo=datetime.timezone.utc).isoformat()
if mytimer.past_due:
logging.info('The timer is past due!')
logging.info('Python timer trigger function ran at %s', utc_timestamp)
```
To run the code snippet generated through the command palette, note the following:
- The function application is defined and named `app`.
- Confirm that the parameters within the trigger reflect values that correspond with your storage account.
- The name of the file must be `function_app.py`.
## Programming Model V2 (Preview)
The new programming model in Azure Functions Python delivers an experience that aligns with Python development principles, and subsequently with commonly used Python frameworks.
The improved programming model requires fewer files than the default model, and specifically eliminates the need for a configuration file (`function.json`). Instead, triggers and bindings are represented in the `function_app.py` file as decorators. Moreover, functions can be logically organized with support for multiple functions to be stored in the same file. Functions within the same function application can also be stored in different files, and be referenced as blueprints.
To learn more about using the new Python programming model for Azure Functions, see the [Azure Functions Python developer guide](https://aka.ms/pythondeveloperguide). Note that in addition to the documentation, [hints](https://aka.ms/functions-python-hints) are available in code editors that support type checking with PYI files.
To learn more about the new programming model for Azure Functions in Python, see [Programming Models in Azure Functions](https://aka.ms/functions-programming-models).