# Contributing to Azure Python SDK

If you would like to become an active contributor to this project please
follow the instructions provided in [Microsoft Azure Projects Contribution Guidelines](https://opensource.microsoft.com/collaborate/).

## Generated code

If you want to contribute to a file that is generated (header contains `Code generated by Microsoft (R) AutoRest Code Generator.`), the best approach to open a PR on the initial Swagger specification, as we can NOT merge a PR on generated code (it would be replaced by next generation). See https://github.com/Azure/azure-rest-api-specs/ for details.

## Tools Overview

We utilize a variety of tools to ensure smooth development, testing, and code quality for the Azure Python SDK. Below is a list of key tools and their purpose in the workflow:

- azpysdk: The `azpysdk` CLI is our primary tool for running checks locally and in CI. It is an entrypoint provided by the `eng/tools/azure-sdk-tools` package and abstracts all checks (linting, type checking, tests, doc generation, etc.) behind a single command. See the [Tool Usage Guide](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/tool_usage_guide.md) for full details.

- UV: [UV](https://docs.astral.sh/uv/) is a fast package manager that can manage Python versions, run and install Python packages, and be used instead of pip, virtualenv, and more.

- Pytest: [Pytest](https://docs.pytest.org/en/stable/) is the test framework we use for writing and running our unit tests. It supports fixtures, parameterized tests, and other features that make testing more powerful and flexible.

- Pylint: [Pylint](https://pylint.readthedocs.io/en/stable/) is used for code linting to enforce coding standards and catch potential issues early. Maintaining a consistent code style is important, and Pylint helps achieve that goal.

- Mypy and Pyright: Both tools are used for type checking. [Mypy](https://mypy.readthedocs.io/en/stable/) helps verify that type annotations are correct, while [Pyright](https://github.com/microsoft/pyright) provides additional support for type completeness and validation.

- Sphinx: [Sphinx](https://www.sphinx-doc.org/en/master/) is used for generating package documentation. This ensures that contributors and users alike have clear, accessible information about how to use the SDK.

- Bandit: [Bandit](https://bandit.readthedocs.io/en/latest/) is employed to find common security issues in Python code. It performs static analysis and helps us secure the codebase.

- Azure DevOps: Our CI/CD pipelines are managed using [Azure DevOps](https://azure.microsoft.com/products/devops/), ensuring that builds, tests, and deployments are executed consistently and reliably across all contributions.

## Building and Testing

The Azure SDK team's Python CI leverages the `azpysdk` CLI tool to run checks, tests, and linters during PR/CI builds. This means that a dev working locally can reproduce _exactly_ what the build machine is doing.

The `azpysdk` entrypoint is provided by the `eng/tools/azure-sdk-tools` package. For full setup instructions and the list of available checks, see the [Tool Usage Guide](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/tool_usage_guide.md).

### Quick Setup

From the root of your target package:

```
pip install -r dev_requirements.txt
```

This installs `azure-sdk-tools` (which provides `azpysdk`) along with the package's dev dependencies.

### Available Checks

You can discover all available checks by running `azpysdk --help`. Some common checks:

```
azpysdk pylint .        # Lint with pylint
azpysdk mypy .          # Type check with mypy
azpysdk pyright .       # Type check with pyright
azpysdk verifytypes .   # Verify type completeness
azpysdk sphinx .        # Build documentation
azpysdk bandit .        # Security analysis
azpysdk black .         # Code formatting
azpysdk verifywhl .     # Verify wheel contents
azpysdk verifysdist .   # Verify sdist contents
azpysdk import_all .    # Verify all imports resolve
azpysdk apistub .       # Generate API stub
azpysdk samples .       # Run samples
azpysdk breaking .      # Check for breaking changes
azpysdk devtest .       # Test against dev feed dependencies
```

### Running from the repo root

`azpysdk` also supports globbing and comma-separated package names when invoked from the repo root:

```
azure-sdk-for-python> azpysdk import_all azure-storage*
azure-sdk-for-python> azpysdk pylint azure-storage-blob,azure-core
```

### Isolated environments

To run a check in a completely fresh virtual environment, add `--isolate`:

```
azpysdk pylint . --isolate
```

### Custom Pytest Arguments

When running test-related checks, you can pass additional arguments to `pytest` after `--`:

```
azpysdk devtest . -- --pdb
```

### Performance Testing

SDK performance testing is supported via the custom `perfstress` framework. For full details on this framework, and how to write and run tests for an SDK - see the [perfstress tests documentation](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/dev/perfstress_tests.md).

### More Reading

We maintain an [additional document](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/eng_sys_checks.md) that has a ton of detail as to what is actually _happening_ in these executions. That document covers:

- [Static analysis checks](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/eng_sys_checks.md#static-analysis-checks) (MyPy, Pyright, Pylint, Sphinx, Bandit, etc.)
- [Install and test checks](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/eng_sys_checks.md#install-and-test-checks) (whl, sdist, mindependency, latestdependency, devtest, regression)
- [PR validation](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/eng_sys_checks.md#pr-validation) (subset that runs on every pull request)
- [Nightly and release checks](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/eng_sys_checks.md#nightly-and-release) (full check set including latestdependency, whl_no_aio, import_all)
- [Weekly analyze checks](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/eng_sys_checks.md#weekly-analyze-checks) (next-generation tool versions)
- [pyproject.toml configuration](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/eng_sys_checks.md#the-pyprojecttoml) (enabling/disabling checks per package, analyze_python_version override)
- [Skipping checks at queue time](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/eng_sys_checks.md#skipping-checks-at-queue-time)

### Package Index Configuration

This repo uses Central Feed Services (CFS) as the default package source for CI, and prefers it for local development over PyPI.

 A repo-root `uv.toml` configures uv to use the CFS feed automatically. 
 
 To use the feed with standard `pip`, use the `--index-url` flag. For example:

 ```bash
 pip install <pkg> --index-url https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-python/pypi/simple/
 ```

 #### `azpysdk` Configuration
 
  The `azpysdk` tool automatically configures pip and uv subprocesses to use the CFS feed by setting the `PIP_INDEX_URL` and `UV_DEFAULT_INDEX` environment variables. If you have already set these variables to a different feed, `azpysdk` will respect your configuration and won't override them.
  
If you wish to bypass CFS and install directly from PyPI, use the `--pypi` flag to pull from PyPI:

```
azpysdk --pypi <command>
```

#### Authentication for upstream pull-through
When installing a package version not yet cached in the CFS feed, it needs to be pulled through from PyPI upstream, which requires authentication. 

Below are options for authenticating:

**Authenticate in terminal (with uv):**

This requires the Azure CLI. First run: 

```bash
az login
```

Then:

```bash
export UV_INDEX_AZURE_SDK_USERNAME=x
export UV_INDEX_AZURE_SDK_PASSWORD=$(az account get-access-token --resource 499b84ac-1321-427f-aa17-267ca6975798 --query accessToken -o tsv)
```

**Create a PAT in Azure DevOps:**

1. Go to [https://dev.azure.com/azure-sdk](https://dev.azure.com/azure-sdk)
2. Click the user settings button in the top right corner next to your profile picture
3. Select "Personal access tokens"
4. Click "New Token"
5. Give it a name (e.g., "Azure SDK Python Feed Access")
6. Set expiration as needed
7. Under "Scopes" -> "Packaging", select "Read, write, & manage"
8. Click "Create"
9. Copy the token and use it in your environment:

```bash
export UV_INDEX_AZURE_SDK_USERNAME=x
export UV_INDEX_AZURE_SDK_PASSWORD=<your-pat-token>
```

Or for pip:
```bash
export PIP_INDEX_URL="https://your-azure-username:your-pat-token@pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-python/pypi/simple/"
```

**To override the CFS index and use PyPI with uv:**
```bash
uv pip install <package> --index-url https://pypi.org/simple/
```

### Dev Feed
Daily dev build version of Azure sdk packages for python are available and are uploaded to Azure devops feed daily. Below is the link to Azure devops feed.
[`https://dev.azure.com/azure-sdk/public/_packaging?_a=feed&feed=azure-sdk-for-python`](https://dev.azure.com/azure-sdk/public/_packaging?_a=feed&feed=azure-sdk-for-python)

##### To install latest dev build version of a package
```
pip install <package-name> --extra-index-url https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-python/pypi/simple --pre
```

#### To Install a specific dev build version of a package
For e.g.
```
pip install azure-appconfiguration==1.0.0b6.dev20191205001 --extra-index-url https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-python/pypi/simple
```

To test a package being developed against latest dev build version of dependent packages:
a. cd to package root folder
b. run `azpysdk devtest`

```
azpysdk devtest .
```

This check will fail if installed dependent packages are not dev build version.

## Samples

### Third-party dependencies

Third party libraries should only be included in samples when necessary to demonstrate usage of an Azure SDK package; they should not be suggested or endorsed as alternatives to the Azure SDK.

When code samples take dependencies, readers should be able to use the material without significant license burden or research on terms. This goal requires restricting dependencies to certain types of open source or commercial licenses.

Samples may take the following categories of dependencies:

- **Open-source** : Open source offerings that use an [Open Source Initiative (OSI) approved license](https://opensource.org/licenses). Any component whose license isn't OSI-approved is considered a commercial offering. Prefer OSS projects that are members of any of the [OSS foundations that Microsoft is part of](https://opensource.microsoft.com/ecosystem/). Prefer permissive licenses for libraries, like [MIT](https://opensource.org/license/MIT) and [Apache 2](https://opensource.org/license/apache-2-0). Copy-left licenses like [GPLv3](https://opensource.org/license/gpl-3-0) are acceptable for tools, and OSs. [Kubernetes](https://github.com/kubernetes/kubernetes), [Linux](https://github.com/torvalds/linux), and [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) are examples of this license type. Links to open source components should be to where the source is hosted, including any applicable license, such as a GitHub repository (or similar).

- **Commercial**: Commercial offerings that enable readers to learn from our content without unnecessary extra costs. Typically, the offering has some form of a community edition, or a free trial sufficient for its use in content. A commercial license may be a form of dual-license, or tiered license. Links to commercial components should be to the commercial site for the software, even if the source software is hosted publicly on GitHub (or similar).

- **Dual licensed**: Commercial offerings that enable readers to choose either license based on their needs. For example, if the offering has an OSS and commercial license, readers can  choose between them. [MySql](https://github.com/mysql/mysql-server) is an example of this license type.

- **Tiered licensed**: Offerings that enable readers to use the license tier that corresponds to their characteristics. For example, tiers may be available for students, hobbyists, or companies with defined revenue  thresholds. For offerings with tiered licenses, strive to limit our use in tutorials to the features available in the lowest tier. This policy enables the widest audience for the article. [Docker](https://www.docker.com/), [IdentityServer](https://duendesoftware.com/products/identityserver), [ImageSharp](https://sixlabors.com/products/imagesharp/), and [Visual Studio](https://visualstudio.com) are examples of this license type.

In general, we prefer taking dependencies on licensed components in the order of the listed categories. In cases where the category may not be well known, we'll document the category so that readers understand the choice that they're making by using that dependency.

## Code of Conduct
This project's code of conduct can be found in the
[CODE_OF_CONDUCT.md file](https://github.com/Azure/azure-sdk-for-python/blob/main/CODE_OF_CONDUCT.md)
(v1.4.0 of the https://contributor-covenant.org/ CoC).
