diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 000000000..8e52ba28f --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,32 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/python +{ + "name": "Python VS Code Flask Tutorial", + // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + "image": "mcr.microsoft.com/devcontainers/python:1-3.12-bullseye", + + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Use 'postCreateCommand' to run commands after the container is created. + "postCreateCommand": "pip3 install --user -r requirements.txt", + + // Configure tool-specific properties. + "customizations": { + "vscode": { + "extensions": [ + "ms-python.python", + "ms-python.black-formatter", + "ms-python.vscode-pylance", + "charliermarsh.ruff", + "ms-python.debugpy" + ] + } + } + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..f33a02cd1 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for more information: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates +# https://containers.dev/guide/dependabot + +version: 2 +updates: + - package-ecosystem: "devcontainers" + directory: "/" + schedule: + interval: weekly diff --git a/.vscode/launch.json b/.vscode/launch.json index d3e8cf2e6..9a2737d78 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,121 +5,21 @@ "version": "0.2.0", "configurations": [ { - "name": "Python: runserver.py", - "type": "python", - "request": "launch", - "program": "${workspaceFolder}/runserver.py", - }, - { - "name": "Python: Current File", - "type": "python", - "request": "launch", - "program": "${file}", - "env": { - "FLASK_ENV": "development" - } - }, - { - "name": "Python: Attach", - "type": "python", - "request": "attach", - "localRoot": "${workspaceFolder}", - "remoteRoot": "${workspaceFolder}", - "port": 3000, - "secret": "my_secret", - "host": "localhost" - }, - { - "name": "Python: Terminal (integrated)", - "type": "python", - "request": "launch", - "program": "${file}", - "console": "integratedTerminal" - }, - { - "name": "Python: Terminal (external)", - "type": "python", - "request": "launch", - "program": "${file}", - "console": "externalTerminal" - }, - { - "name": "Python: Django", - "type": "python", - "request": "launch", - "program": "${workspaceFolder}/manage.py", - "args": [ - "runserver", - "--noreload", - "--nothreading" - ], - "debugOptions": [ - "RedirectOutput", - "Django" - ] - }, - { - "name": "Python: Flask (0.11.x or later)", - "type": "python", + "name": "Python Debugger: Flask", + "type": "debugpy", "request": "launch", "module": "flask", "env": { - "FLASK_APP": "hello_app.webapp" + "FLASK_APP": "hello_app.webapp", + "FLASK_DEBUG": "1" }, "args": [ "run", "--no-debugger", - "--no-reload" // Remove to auto-reload modified pages - ] - }, - { - "name": "Python: Module", - "type": "python", - "request": "launch", - "module": "module.name" - }, - { - "name": "Python: Pyramid", - "type": "python", - "request": "launch", - "args": [ - "${workspaceFolder}/development.ini" - ], - "debugOptions": [ - "RedirectOutput", - "Pyramid" - ] - }, - { - "name": "Python: Watson", - "type": "python", - "request": "launch", - "program": "${workspaceFolder}/console.py", - "args": [ - "dev", - "runserver", - "--noreload=True" - ] - }, - { - "name": "Python: All debug Options", - "type": "python", - "request": "launch", - "pythonPath": "${config:python.pythonPath}", - "program": "${file}", - "module": "module.name", - "env": { - "VAR1": "1", - "VAR2": "2" - }, - "envFile": "${workspaceFolder}/.env", - "args": [ - "arg1", - "arg2" + "--no-reload" ], - "debugOptions": [ - "RedirectOutput" - ] + "jinja": true, + "justMyCode": true } ] } diff --git a/Dockerfile b/Dockerfile index 0f62521f9..4c775f6b9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Pull a pre-built alpine docker image with nginx and python3 installed -FROM tiangolo/uwsgi-nginx-flask:python3.6-alpine3.7 +FROM tiangolo/uwsgi-nginx:python3.8-alpine-2020-12-19 # Set the port on which the app runs; make both values the same. # diff --git a/README.md b/README.md index 301c7ea4e..068a76fd5 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,32 @@ -This sample contains the completed program from the tutorial, [Using Flask in Visual Studio Code](https://code.visualstudio.com/docs/python/tutorial-flask). Intermediate steps are not included. +# Python/Flask Tutorial for Visual Studio Code -It also contains the Dockerfile and uwsgi.ini files necessary to build a container with a production server. The resulting image works both locally and when deployed to Azure App Service. See [Deploy Python using Docker containers](https://code.visualstudio.com/docs/python/tutorial-deploy-containers). +* This sample contains the completed program from the tutorial, make sure to visit the link: [Using Flask in Visual Studio Code](https://code.visualstudio.com/docs/python/tutorial-flask). Intermediate steps are not included. -The `startup.py` file, for its part, is specifically for deploying to Azure App Service on Linux without containers. Because the app code is in its own *module* in the `hello_app` folder (which has an `__init__.py`), trying to start the Gunicorn server within App Service on Linux produces an "Attempted relative import in non-package" error. The `startup.py` file, therefore, is just a shim to import the app object from the `hello_app` module, which then allows you to use startup:app in the Gunicorn command line (see `startup.txt`). +* It also contains the *Dockerfile* and *uwsgi.ini* files necessary to build a container with a production server. The resulting image works both locally and when deployed to Azure App Service. See [Deploy Python using Docker containers](https://code.visualstudio.com/docs/python/tutorial-deploy-containers). + +* To run the app locally: + 1. Run the command `cd hello_app`, to change into the folder that contains the Flask app. + 1. Run the command `set FLASK_APP=webapp` (Windows cmd) or `FLASK_APP=webapp` (macOS/Linux) to point to the app module. + 1. Start the Flask server with `flask run`. + +## The startup.py file + +In the root folder, the `startup.py` file is specifically for deploying to Azure App Service on Linux without using a containerized version of the app (that is, deploying the code directly, not as a container). + +Because the app code is in its own *module* in the `hello_app` folder (which has an `__init__.py`), trying to start the Gunicorn server within App Service on Linux produces an "Attempted relative import in non-package" error. + +The `startup.py` file, therefore, is a shim to import the app object from the `hello_app` module, which then allows you to use startup:app in the Gunicorn command line (see `startup.txt`). + +## Contributing Contributions to the sample are welcome. When submitting changes, also consider submitting matching changes to the tutorial, the source file for which is [tutorial-flask.md](https://github.com/Microsoft/vscode-docs/blob/master/docs/python/tutorial-flask.md). -# Contributing +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. -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 automatically determines 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. -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. +## Additional details -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). -For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or -contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. +* This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +* For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +* Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..869fdfe2b --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + + * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) + * Full paths of source file(s) related to the manifestation of the issue + * The location of the affected source code (tag/branch/commit or direct URL) + * Any special configuration required to reproduce the issue + * Step-by-step instructions to reproduce the issue + * Proof-of-concept or exploit code (if possible) + * Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). + + diff --git a/hello_app/__init__.py b/hello_app/__init__.py index cf1f4140e..eb82cbf69 100644 --- a/hello_app/__init__.py +++ b/hello_app/__init__.py @@ -1,2 +1,2 @@ -from flask import Flask -app = Flask(__name__) +from flask import Flask # Import the Flask class +app = Flask(__name__) # Create an instance of the class for our use diff --git a/hello_app/templates/hello_there.html b/hello_app/templates/hello_there.html index 7c54f6437..de1ef49d1 100644 --- a/hello_app/templates/hello_there.html +++ b/hello_app/templates/hello_there.html @@ -6,6 +6,11 @@ Hello, Flask - Hello there, {{ name }}! It's {{ date.strftime("%A, %d %B, %Y at %X") }}. + {%if name %} + Hello there, {{ name }}! It's {{ date.strftime("%A, %d %B, %Y at %X") }}. + {% else %} + What's your name? Provide it after /hello/ in the URL. + {% endif %} + diff --git a/hello_app/views.py b/hello_app/views.py index d40756488..8f714ea90 100644 --- a/hello_app/views.py +++ b/hello_app/views.py @@ -6,16 +6,17 @@ def home(): return render_template("home.html") -@app.route("/about") +@app.route("/about/") def about(): return render_template("about.html") -@app.route("/contact") +@app.route("/contact/") def contact(): return render_template("contact.html") +@app.route("/hello/") @app.route("/hello/") -def hello_there(name): +def hello_there(name = None): return render_template( "hello_there.html", name=name, diff --git a/hello_app/webapp.py b/hello_app/webapp.py index c76b9bcb3..56386def8 100644 --- a/hello_app/webapp.py +++ b/hello_app/webapp.py @@ -1,4 +1,4 @@ -"""Entry point for the application.""" +# Entry point for the application. from . import app # For application discovery by the 'flask' command. from . import views # For import side-effects of setting up routes. diff --git a/requirements.txt b/requirements.txt index 34ffbb7b2..e3e9a71d9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1 @@ -click==6.7 -Flask==1.0.2 -itsdangerous==0.24 -Jinja2==2.10 -MarkupSafe==1.0 -Werkzeug==0.14.1 +Flask diff --git a/startup.py b/startup.py index 3c7d57d05..9fa523781 100644 --- a/startup.py +++ b/startup.py @@ -1,10 +1,12 @@ -# In this sample, the Flask app object is contained within the hello_app *module*; -# that is, hello_app contains an __init__.py along with relative imports. Because -# of this structure, a file like webapp.py cannot be run directly as the startup -# file through Gunicorn; the result is "Attempted relative import in non-package". -# -# The solution is to provide a simple alternate startup file, like this present -# startup.py, that just imports the app object. You can then just specify -# startup:app in the Gunicorn command. +""" +In this sample, the Flask app object is contained within the hello_app *module*; +that is, hello_app contains an __init__.py along with relative imports. Because +of this structure, a file like webapp.py cannot be run directly as the startup +file through Gunicorn; the result is "Attempted relative import in non-package". + +The solution is to provide a simple alternate startup file, like this present +startup.py, that just imports the app object. You can then just specify +startup:app in the Gunicorn command. +""" from hello_app.webapp import app diff --git a/test_test1.py b/test_test1.py new file mode 100644 index 000000000..da8dc03d2 --- /dev/null +++ b/test_test1.py @@ -0,0 +1,2 @@ +def test_mock(): + assert True