# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['azdebugrelay']

package_data = \
{'': ['*']}

install_requires = \
['debugpy>=1.2.1,<2.0.0']

setup_kwargs = {
    'name': 'azure-debug-relay',
    'version': '0.3.4',
    'description': 'Cross-network remote debugging for Python',
    'long_description': '# Azure Debug Relay for Python\n\nAzure Debug Relay - is a [Visual Studio Code](https://code.visualstudio.com/) extension and a Python package for distributed remote debugging.\n\n* [Azure Debug Relay extension](https://marketplace.visualstudio.com/items?itemName=VladKolesnikov-vladkol.azure-debug-relay) on Visual Studio Marketplace\n* [azure-debug-relay](https://pypi.org/project/azure-debug-relay/) package on PyPI\n\nAzure Debug Relay uses [debugpy](https://github.com/microsoft/debugpy) and [Azure Relay](https://docs.microsoft.com/en-us/azure/azure-relay/relay-what-is-it) service to create a debugging tunnel between 2 machines:\n\n1. You local Visual Studio Code debugger in `listen` mode.\n1. You remote code in `attach` mode.\n\nBoth machines can be isolated behind NAT or virtual networks - all they need is to be able to connect to Azure Relay resource.\nAzure Relay carries a secure tunnel, just as if these machines were in the same VPN.\n\n![Azure Relay Debugging Bridge](https://raw.githubusercontent.com/vladkol/azure-debug-relay/main/images/debug-relay-diagram.png)\n\nThe debugging tunnel is handled by **[Azure Relay Bridge](https://github.com/vladkol/azure-relay-bridge)** utility which is downloaded and installed automatically by Azure Debug Relay. Azure Relay Bridge can maintain secure TCP and UDP tunnels for different purposes.\n\n> We currently use a private fork of [Azure Relay Bridge](https://github.com/Azure/azure-relay-bridge) repo.\n\n## Requirements\n\n* Python 3.6+\n* debugpy 1.2.1+\n* Visual Studio Code 1.34+ (for using VS Code extension)\n\nAzure Relay Bridge tool is a .NET Core application, so you may need  to install `apt-transport-https` and other .NET Core 3.1 Runtime prerequisites on [Linux](https://docs.microsoft.com/en-us/dotnet/core/install/linux) and [Windows](https://docs.microsoft.com/en-us/dotnet/core/install/windows?tabs=netcore31).\n\n> You don\'t have to install .NET Runtime itself - Azure Relay Bridge builds are self-contained.\n\n### Supported Operating Systems\n\n* Ubuntu 18+\n* Debian 10+\n* macOS 10+\n* Windows 10\n\n## Installation\n\n**On the debugger side (usually your dev machine with Visual Studio code)**:\n\n> Install [Azure Debug Relay extension](https://marketplace.visualstudio.com/items?itemName=VladKolesnikov-vladkol.azure-debug-relay) from Visual Studio Marketplace.\n\n**On the server side**:\n\n> `python3 -m pip install azure-debug-relay`\n\n## Usage\n\nBefore you start debugging with Azure Debug Relay, there are 3 places you configure it:\n\n1. Azure Portal.\n1. Local machine where you run Visual Studio Code and its Python debugger.\n1. Remote machine where you run the same code files that open locally in VS Code.\n\n### In Azure Portal\n\n1. [Create Azure Relay resource](https://ms.portal.azure.com/#create/Microsoft.Relay). Better make one in a region closest to your location.\n1. Once created, switch to the resource, and select `Hybrid Connections` option in the vertical panel.\n1. Add a hybrid connection (`+ Hybrid Connection` button), give it a memorable name (e.g. `test` 🙂) - this is your **Hybrid Connection Name**.\n1. Switch to that new hybrid connection, then select `Shared Access Policies` in the vertical panel.\n1. Add a new policy with `Send` and `Listen` permissions.\n1. Once created, copy its `Primary Connection String`, this is your **Connection String**.\n\n#### **Azure CLI version**\n\nChoose your name instead of `mydebugrelay1` for an Azure Relay resource, and your custom name for Hybrid Connection instead of `debugrelayhc1`.\n\n```cmd\naz group create --name debugRelayResourceGroup --location westus2\n\naz relay namespace create --resource-group debugRelayResourceGroup --name mydebugrelay1 --location westus2\n\naz relay hyco create --resource-group debugRelayResourceGroup --namespace-name mydebugrelay1 --name debugrelayhc1\n\naz relay hyco authorization-rule create --resource-group debugRelayResourceGroup --namespace-name mydebugrelay1 --hybrid-connection-name debugrelayhc1 --name sendlisten --rights Send Listen\n\naz relay hyco authorization-rule keys list --resource-group debugRelayResourceGroup --namespace-name mydebugrelay1 --hybrid-connection-name debugrelayhc1 --name sendlisten\n```\n\nLast command will show you something like this:\n\n```json\n{\n  "keyName": "sendlisten",\n  "primaryConnectionString": "Endpoint=sb://mydebugrelay1.servicebus.windows.net/;SharedAccessKeyName=sendlisten;SharedAccessKey=REDACTED1;EntityPath=debugrelayhc1",\n  "primaryKey": "REDACTED1",\n  "secondaryConnectionString": "Endpoint=sb://mydebugrelay1.servicebus.windows.net/;SharedAccessKeyName=sendlisten;SharedAccessKey=REDACTED2;EntityPath=debugrelayhc1",\n  "secondaryKey": "REDACTED2"\n}\n```\n\nUse `primaryConnectionString` or `secondaryConnectionString` value as your **Connection String**.\n\n**Hybrid Connection Name** would be the one you choose instead of `debugrelayhc1`.\n</details>\n\n### Remotely with `remote_server_demo.py` or your code\n\nRemote Server example (in `samples/simple_demo/remote_server_demo.py`) assumes that Azure Relay credentials will are passes via `.azrelay.json` file in the current directory or via environment variables. Therefore, you have 2 options:\n\n**Option 1**: Create `.azrelay.json` file in your workspace directory root or whatever directory will be "current",\nand set 2 variables:\n\n1. `AZRELAY_CONNECTION_STRING` to your **Connection String**.\n1. `AZRELAY_CONNECTION_NAME` to your **Hybrid Connection Name**.\n\nFor example:\n\n```json\n{\n  "AZRELAY_CONNECTION_STRING": "Endpoint=sb://mydebugrelay1.servicebus.windows.net/;SharedAccessKeyName=sendlisten;SharedAccessKey=REDACTED1;EntityPath=debugrelayhc1",\n  "AZRELAY_CONNECTION_NAME": "debugrelayhc1"\n}\n```\n\nMake sure you add `.azrelay.json` to `.gitignore` so won\'t be committed.\n\n**Option 2**: You can assign these 2 variables as environment variables: `AZRELAY_CONNECTION_STRING` and `AZRELAY_CONNECTION_NAME` instead.\n\n### Prepare local Visual Studio Code\n\nUse `.azrelay.json` file in the root of your workspace as above or `.vscode/settings.json` with the following settings (actual values are ones you have):\n\n```json\n{\n  "azure-debug-relay.azrelay-connection-string": "Endpoint=sb://your-relay.servicebus.windows.net/;SharedAccessKeyName=key_name;SharedAccessKey=REDACTED;EntityPath=test",\n\n  "azure-debug-relay.azrelay-connection-name": "test",\n}\n```\n\n> Whenever Azure Debug Relay VS Code extension detects non-empty `azure-debug-relay.hybrid-connection-string` and `azure-debug-relay.hybrid-connection-name` settings (`vscode/settings.json`) or `AZRELAY_CONNECTION_STRING` and `AZRELAY_CONNECTION_NAME` in `.azrelay.json` file, it launches Azure Relay Bridge every time a debugging session with debugpy in `listen` mode is about to begin. If extension settings are not empty and `.azrelay.json` is present, Azure Relay Bridge prefers values from the extension settings (`vscode/settings.json`).\n\nVisual Studio Code extension ignores `AZRELAY_CONNECTION_STRING` and `AZRELAY_CONNECTION_NAME` environment variables.\n\n### Start debugging in Visual Studio Code\n\nThis step must be done on your dev machine in Visual Studio Code before launching the remote code.\n\n1. Open `remote_server_demo.py` and put a breakpoint in `do_work()` function.\n1. Makes sure your `.vscode/launch.json` has `Python: Listen 5678` configuration as in this repo\'s `.vscode/launch.json`.\n1. Start debugging in your local Visual Studio Code in `Python: Listen 5678` configuration.\n\nNotice how the debugger maps paths on the local and the remote machines.\nIf your code has a different structure remotely, you may need to provide more sophisticated path mappings. Here is that piece in `.vscode/launch.json`:\n\n```json\n"pathMappings": [\n    {\n        "localRoot": "${workspaceFolder}",\n        "remoteRoot": "."\n    }\n]\n```\n\nIt tells VS Code that the workspace directory locally is mapped to the "current" directory remotely.\n\nWhen the debugger looks goes through a file remotely, it needs to find the corresponding file in your local VS Code workspace.\nWhen debugging `remote_server_demo.py`, the debugger maps `./samples/simple_demo/remote_server_demo.py` remotely to `${workspaceFolder}/samples/simple_demo/remote_server_demo.py` locally.\n\n### Launch the example on the remote machine\n\n1. Clone the repo.\n1. Start `python3 ./samples/simple_demo/remote_server_demo.py --debug=attach`. Notice that current directory must contain `.azrelay.json` file unless configured with environment variables.\n\n> Terminal session where you start #2 must have the repo\'s directory as current directory - for a reason of mapping local and remote directories.\n\nIf everything works as it\'s supposed to, you will hit a breakpoint in your local Visual Studio Code.\n\n## Azure Debug Relay Python API\n\n`remote_server_demo.py` shows how you can use Azure Debug Relay (azure-debug-relay package) with your code.\n\n**azdebugrelay** module contains DebugRelay class that install and launches Azure Relay Bridge:\n\n```python\nfrom azdebugrelay import DebugRelay, DebugMode, debugpy_connect_with_timeout\n\naccess_key_or_connection_string = "AZURE RELAY HYBRID CONNECTION STRING OR ACCESS KEY"\nrelay_connection_name = "HYBRID CONNECTION NAME" # your Hybrid Connection name\ndebug_mode = DebugMode.Connect # or DebugMode.WaitForConnection if connecting from another end\nhybrid_connection_url = "HYBRID CONNECTION URL" # can be None if access_key_or_connection_string is a connection string\nhost = "127.0.0.1" # local hostname or ip address the debugger starts on\nport = 5678\nports = [str(port)] # any available ports that you can use within your machine\ndebugpy_timeout = 15 # 15 seconds for debugpy to connect\n\ndebug_relay = DebugRelay(access_key_or_connection_string, relay_connection_name, debug_mode, hybrid_connection_url, host, ports)\ndebug_relay.open()\n\n# attach to a remote debugger (usually from remote server code) with debug_mode = DebugMode.Connect\ndebugpy_connect_with_timeout(host, port, debugpy_timeout) # use instead of debugpy.connect\n# if debug_mode = DebugMode.WaitForConnection, we are going to listen instead\n# debugpy.listen((host, port))\n# if debug_mode = DebugMode.WaitForConnection, you can start DebugRelay on multiple ports (ports parameter is a list)\n# debugpy.listen must be called with each of these ports\n\n# Debug, debug, debug\n# ...\n# ...\n\ndebug_relay.close()\n```\n\n* `access_key_or_connection_string` - SAS Policy key or Connection String for Azure Relay Hybrid Connection. Must have `Send` and `Listen` permissions\n* `relay_connection_name` - name of the Hybrid Connection\n* `debug_mode` - debug connection mode. `DebugMode.WaitForConnection` when starting in listening mode, `DebugMode.Connect` for attaching to a remote debugger.\n* `hybrid_connection_url` - Hybrid Connection URL. Required when access_key_or_connection_string as an access key, otherwise is ignored and may be None.\n* `host` - Local hostname or ip address the debugger starts on, `127.0.0.1` by default\n* `port` - debugging port, `5678` by default\n\n> We added `debugpy_connect_with_timeout` method on top of **debugpy.connect()**.\nIt accepts `connect_timeout_seconds` parameter - how long it should wait for `debugpy.connect()` to connect.\nIf the connection is not successfully made within the timeout,\nthe debugging session aborts, and that can be handled in your code:\n`debugpy_connect_with_timeout()` returns `True` if the connection was successful, and `False` otherwise.\n\nNotice that DebugRelay accepts multiple ports to work with (**`ports` parameter is a list**).\nThat\'s because Azure Relay Bridge support forwarding on multiple ports.\nThis feature is primarily used by DebugRelay internally\nfor [Simultaneous distributed debugging](#simultaneous-distributed-debugging).\n\n### Azure Machine Learning samples\n\n**Simple Azure ML sample** is located in `samples/azure_ml_simple` directory.\n\nIt has 2 components:\n\n1. `deploy_and_run.py` script that deploys and launches an Azure ML pipeline with a single step.\n2. `steps/train.py` script which contains that simple step.\n\nLook at the [sample\'s readme file](samples/azure_ml_simple/README.md).\n\n**Advanced Azure Machine Learning sample** is located in `samples/azure_ml_advanced`, and demonstrates a complex debugging scenario with parallel steps.\n\nLook at the [advanced sample\'s readme file](samples/azure_ml_advanced/README.md).\n\n## Simultaneous distributed debugging\n\nYou can debug multiple simultaneously running remote nodes using different ports.\nEach execution flow you want to debug must use a separate port - both locally and remotely.\n\nIn Visual Studio code, it is achievable via so called "[compound launch configurations](https://code.visualstudio.com/docs/editor/debugging#_compound-launch-configurations)".\nCompound launch configurations combine multiple launch configurations, and therefore start them at the same time.\n\nEach launch configuration must be a Python `listen` configuration with a unique name and port:\n\n```json\n{\n  "name": "Python: Listen 5678",\n  "type": "python",\n  "request": "attach",\n  "listen": {\n      "host": "127.0.0.1",\n      "port": 5678\n  },\n  "pathMappings": [\n      {\n          "localRoot": "${workspaceFolder}",\n          "remoteRoot": "."\n      }\n  ]\n}\n```\n\nYou need as many launch configurations as number of simultaneous execution flows or nodes you\'d like to debug.\nThen you combine them in `.vscode/launch.json` to as a compound:\n\n```json\n"compounds": [\n  {\n    "name": "Python: AML Adv 2 Listeners",\n    "configurations": [\n      "Python: Listen 5678", \n      "Python: Listen 5679"\n    ]\n  }\n]\n```\n\nRemotely, each node you debug should be aware of the port number it should use.\nThat port number must be passed to `DebugRelay` object and `debugpy_connect_with_timeout()`.\n\n## Troubleshooting\n\nWhy using [Azure Relay Bridge](https://github.com/Azure/azure-relay-bridge) which is a .NET Core application that we have to install and use via `subprocess` calls?\n\nReasons:\n\n1. Azure Relay has SDKs for .NET, Java, and Node. [No Python SDK or examples](https://github.com/Azure/azure-relay/issues/28#issuecomment-390778193).\n1. Azure Relay Bridge does a lot of things we have to implement otherwise. It is a great tool that can help you connecting different networks for many purposes: for RDP, SSH and other protocols over TCP or UDP.\n\nA [private fork](https://github.com/vladkol/azure-relay-bridge) we are currently using is only to provide .NET Core 3.1 builds of the most recent code. There is a pending pul-requests: [one](https://github.com/Azure/azure-relay-bridge/pull/22) and [two](https://github.com/Azure/azure-relay-bridge/pull/19).\n\n### Known issues\n\n> **Extension and python module fail complaining about `AZRELAY_CONNECTION_NAME` or `azrelay-connection-name`**.\n\n**Reason**: It is a breaking change in 0.2.0. We changed configuration and environment variables name from `AZRELAY_NAME` to `AZRELAY_CONNECTION_NAME`. VS Code extension setting names we also renamed:\n\n* `hybrid-connection-string` to **azrelay-connection-string**\n* `azrelay-connection-name` to **azrelay-connection-name**\n\n**Workaround**: Modify your `.azrelay.json`, environment variables or `.vscode/settings.json` files accordingly.\n\n> **On macOS, there may be a situation when Azure Relay Bridge (`azbridge`) cannot connect when creating a local forwarder** (`-L` option).\n\n**Reason**: .NET Core wants you to add your Computer Name to `/etc/hosts` file, and make sure the hostname is configured.\n\n**Workaround**: Make necessary edits of `/etc/hosts` file, and configure hostname:\n\n1. Look for your computer\'s name in `Settings → Sharing`.\n1. Run the following command: `scutil --set HostName "your-computer-name"`. (**replace `your-computer-name` with your computer\'s name**)\n1. Open `/etc/hosts` in a text editor in *sudo* mode (VS Code can save it later in *sudo* mode).\n1. Add the following line (**replace `your-computer-name` with your computer\'s name**). Save the file.\n\n```text\n127.0.0.1   your-computer-name\n```\n\n> **I launched the debugger as described and nothing happened**\n\n**Reason**: you *probably* didn\'t put a breakpoint in your VS Code locally. Make sure that breakpoint is in a place that your server process actually runs through.\n\n> **I do everything right, but nothing works**\n\n**Reason**: Stop all debugging sessions (if any). Kill all `azbridge` processes locally and remotely. Try again.\n\nDoesn\'t help? [File an issue](https://github.com/vladkol/azure-debug-relay/issues/new)! Thank you!\n',
    'author': 'Vlad Kolesnikov',
    'author_email': None,
    'maintainer': None,
    'maintainer_email': None,
    'url': None,
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'python_requires': '>=3.6,<4.0',
}


setup(**setup_kwargs)
