Skip to content

Commit e407c0e

Browse files
committed
Merge branch 'main' of https://github.com/Azure/azure-sdk-for-python into url_formatting
* 'main' of https://github.com/Azure/azure-sdk-for-python: (267 commits) Increment package version after release of azure-servicebus (Azure#21682) [Search] Semantic Configuration (Azure#21497) Increment package version after release of azure-monitor-query (Azure#21686) Increment package version after release of azure-eventgrid (Azure#21687) Increment package version after release of azure-messaging-webpubsubservice (Azure#21711) Increment package version after release of azure-schemaregistry (Azure#21703) Increment package version after release of azure-schemaregistry-avroserializer (Azure#21729) Increment package version after release of azure-loganalytics (Azure#21743) Increment package version after release of azure-mixedreality-authentication (Azure#21745) Increment package version after release of azure-mixedreality-remoterendering (Azure#21761) TURN: Adding RouteType optional parameter to GetRelayConfiguration (Azure#21698) Sync eng/common directory with azure-sdk-tools for PR 2290 (Azure#21791) Update test_proxy_migration_guide.md (Azure#21795) Add better logging to GetExistingPackageVersions (Azure#21782) Update packaging.md for Python 3 only packages (Azure#21720) Make sure clean-up scripts return collections (Azure#21785) fix bug in prepare relaease for new packages that have never been released (Azure#21783) remove unused import (Azure#21779) Prefix matrix generation service directory sparse checkout with 'sdk' (Azure#21769) [AutoRelease] t2-loganalytics-2021-11-16-55983 (Azure#21776) ...
2 parents 92d8485 + a76f5c9 commit e407c0e

File tree

3,910 files changed

+540597
-457984
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

3,910 files changed

+540597
-457984
lines changed

.github/CODEOWNERS

+2-1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
/sdk/communication/ @acsdevx-msft
4242
/sdk/communication/azure-communication-phonenumbers/ @RoyHerrod @danielav7 @whisper6284 @AlonsoMondal
4343
/sdk/communication/azure-communication-sms/ @RoyHerrod @arifibrahim4
44+
/sdk/communication/azure-communication-identity/ @Azure/acs-identity-sdk
4445

4546
# PRLabel: %KeyVault
4647
/sdk/keyvault/ @schaabs @chlowell @mccoyp @YalinLi0312
@@ -65,7 +66,7 @@
6566
/sdk/containerservice/ @samkreter @zqingqing1 @GaneshaThirumurthi
6667

6768
# PRLabel: %Cosmos
68-
/sdk/cosmos/ @southpolesteve @zfoster
69+
/sdk/cosmos/ @kushagraThapar @simorenoh @simplynaveen20 @xinlian12 @moderakh
6970

7071
# PRLabel: %Data Factory
7172
/sdk/datafactory/ @hvermis

doc/dev/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Overview of the documents:
77
- [Release](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/dev/release.md) : How to release a package when ready
88
- [Packaging](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/dev/packaging.md) : How to organize packaging information for packages under `azure`
99
- [Testing](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/dev/tests.md): How to write unit and functional tests for a library
10-
- [Docstrings and Type hints](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/dev/docstring_typehint.md): How to document an SDK for compatability with internal tools (API View) and our documentation at [MS Docs][ms_docs] and the [azure.github.io][azure_github_io] site.
10+
- [Docstrings and Type hints](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/dev/docstring_typehint.md): How to document an SDK for compatibility with internal tools (API View) and our documentation at [MS Docs][ms_docs] and the [azure.github.io][azure_github_io] site.
1111

1212
The [mgmt](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/dev/mgmt) folder contains information specific to management packages (i.e. packages prefixed by `azure-mgmt`)
1313

doc/dev/get_unreleased_package_guide.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ The following figure shows the wheel and zip of the package.Click to download th
1616
(1) If there is no link in the figure above, it may be folded. You can also find it in the check.
1717
![img.png](unreleased_package_guide_example3.png)
1818

19-
(2) [Private repo](https://github.com/Azure/azure-rest-api-specs-pr) can only be triggered when the target branch is `main`
19+
(2) The private Azure/azure-rest-api-specs-pr repo can only be triggered when the target branch is `main`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
This file claims the rules how Python decide next version number for package.
2+
3+
The package version contains two part:
4+
1. the package is preview or stable?
5+
2. version number
6+
7+
# How to judge preview or stable?
8+
Python SDK is generated with [swagger](https://github.com/Azure/azure-rest-api-specs), so if swagger content is preview,
9+
the package is preview; if swagger content is stable, the package is stable.
10+
11+
(1) For single api package(for example: [datadog](https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/datadog)),
12+
as long as the current tag is preview, the package version should be preview
13+
14+
(2) For multi api package(for example: [network](https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/network/azure-mgmt-network)),
15+
there will be `DEFAULT_API_VERSION`(for example: [`DEFAULT_API_VERSION` of network](https://github.com/Azure/azure-sdk-for-python/blob/59709af16b7cd29a51d562137bc5bbfdf53f9327/sdk/network/azure-mgmt-network/azure/mgmt/network/_network_management_client.py#L60)).
16+
As long as it is preview, then the package version is preview.
17+
18+
(note1: If the name of tag contains 'preview' or the tag contains files of 'preview' folder, then the tag is preview tag.
19+
For exampe: [preview tag](https://github.com/Azure/azure-rest-api-specs/tree/main/specification/compute/resource-manager#tag-package-2021-06-01-preview))
20+
21+
(note2: If the api-version contains 'preview', then it is preview api-version. for example: [preview api-version](https://github.com/Azure/azure-rest-api-specs/blob/69eacf00a36d565d3220d5dd6f4a5293664f1ae9/specification/network/resource-manager/Microsoft.Network/preview/2015-05-01-preview/network.json#L6))
22+
23+
(note3: The difference about single api and multi api, please see the detailed file)
24+
25+
(note4: preview package version contains `b`, for example: `1.0.0b1`)
26+
27+
# How to decide next version number
28+
1\. If current version is preview version, the new tag is preview tag, then next version is `x.x.xbx+1`
29+
30+
2\. If current version is stable version, the new tag is stable tag, then :
31+
* if there is breaking change, next version is `x+1.x.x`
32+
* if there is new feature but no breaking change, next version is `x.x+1.x`
33+
* if there is only bugfix, next version is `x.x.x+1`
34+
35+
3\. If current version is stable version, the new tag is preview tag, calculate version number according to `2`
36+
and then append `b1` in the result
37+
38+
39+
According to the up rules, we could summarize all the possibilities in the following table:
40+
41+
![img.png](version_summary.png)
42+
43+
(`-` means that this item doesn't influence result)
44+
11.1 KB
Binary file not shown.
14.2 KB
Loading

doc/dev/packaging.md

+62-26
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,25 @@
11
# Azure packaging
22

3-
This article describes how to declare setup.py and all packaging information for packages inside the `azure` namespace
3+
This article describes the recommendations for defining namespace packaging to release a package inside the `azure` namespace. Being inside the `azure` namespace means that a service `myservice` can be imported using:
4+
```python
5+
import azure.myservice
6+
```
47

58
Namespace packaging is complicated in Python, here's a few reading if you still doubt it:
69
- https://packaging.python.org/guides/packaging-namespace-packages/
710
- https://www.python.org/dev/peps/pep-0420/
811
- https://github.com/pypa/sample-namespace-packages
912

10-
This article describes the recommendation on how to define namespace packaging to release a package inside the `azure` namespace. Being inside the `azure` namespace meaning you have a service `myservice` that you want to import using:
11-
```python
12-
import azure.myservice
13-
```
14-
1513
Note:
16-
- This article is not about setup.py or setup.cfg or the right way to *write* the packaging, it's about what instructions you should use to achieve this. If you are fluent in setuptools, and prefer to write the suggestions in setup.cfg and not in setup.py, this is not a concern.
14+
While this article provides an example using setup.py, this can also be achieved with setup.cfg or other methods, as long as the constraints on the final wheels/sdist are met.
15+
16+
*This page has been updated to be Python 3 only packages as we do not recommend supporting Python 2 after January 1st 2022.* If you still want to support Python 2 for some reasons, there is a section at the bottom with some details (or you have the Github history, to read the page as it was on November 1st 2021).
1717

1818
# What are the constraints?
1919

2020
We want to build sdist and wheels in order to follow the following constraints:
2121
- Solution should work with *recent* versions of pip and setuptools (not the very latest only, but not archaeology either)
22-
- Wheels must work with Python 2.7 and 3.6+
23-
- easy-install scenario is a plus, but cannot be considered critical anymore
22+
- Wheels must work with Python 3.7+
2423
- mixed dev installation and PyPI installation should be explicitly addressed
2524

2625
# What do I do in my files to achieve that
@@ -55,13 +54,9 @@ The "packages" section MUST EXCLUDE the `azure` package. Example:
5554
]),
5655
```
5756

58-
The "extras_requires" section MUST include a conditional dependency on "azure-nspkg" for Python 2. There is also a conditional dependency on "typing" for Python 3.5 because of the type-hinting for Python 3.5 and above. Example:
59-
57+
Since the package is Python 3 only, you must notify it in the setup.py as well:
6058
```python
61-
extras_require={
62-
":python_version<'3.0'": ['azure-nspkg'],
63-
":python_version<'3.5'": ['typing'],
64-
}
59+
python_requires=">=3.7",
6560
```
6661

6762
Example of a full setup.py
@@ -113,16 +108,15 @@ setup(
113108
classifiers=[
114109
'Development Status :: 4 - Beta',
115110
'Programming Language :: Python',
116-
'Programming Language :: Python :: 2',
117-
'Programming Language :: Python :: 2.7',
111+
'Programming Language :: Python :: 3 :: Only',
118112
'Programming Language :: Python :: 3',
119-
'Programming Language :: Python :: 3.5',
120-
'Programming Language :: Python :: 3.6',
121113
'Programming Language :: Python :: 3.7',
122114
'Programming Language :: Python :: 3.8',
123115
'Programming Language :: Python :: 3.9',
116+
'Programming Language :: Python :: 3.10',
124117
'License :: OSI Approved :: MIT License',
125118
],
119+
python_requires=">=3.7",
126120
zip_safe=False,
127121
packages=find_packages(exclude=[
128122
'tests',
@@ -134,17 +128,59 @@ setup(
134128
'msrestazure>=0.4.32,<2.0.0',
135129
'azure-common~=1.1',
136130
],
137-
extras_require={
138-
":python_version<'3.0'": ['azure-nspkg'],
139-
":python_version<'3.5'": ['typing'],
140-
}
141131
)
142132
```
143133

144-
This syntax works with setuptools >= 17.1 and pip >= 6.0, which is considered enough to support in 2019.
134+
This syntax works with setuptools >= 24.2.0 (July 2016) and pip >= 9.0 (Nov 2016), which is considered enough to support in 2021.
135+
136+
Since the package is Python 3 only, do NOT make this wheel universal. This usually means you should NOT have `universal=1` in the `setup.cfg`. It may mean you can completely remove the file if `universal` was the only configuration option inside.
145137

146138
# How can I check if my packages are built correctly?
147139

148-
- wheels must NOT contain a `azure/__init__.py` file (you can open it with a zip util to check)
149-
- wheels installs `azure-nskpg` ONLY on Python 2.
140+
- wheel file must NOT contain a `azure/__init__.py` file (you can open it with a zip util to check)
141+
- wheel file name suffix is `py3-none-any`, and NOT `py2.py3-none-any`.
150142
- sdist must contain a `azure/__init__.py` file that declares `azure` as a namespace package using the `pkgutil` syntax
143+
144+
# I already have a package that supports Python 2, can I get short version on how to udpate to Python 3 only?
145+
146+
- Remove "universal" from setup.cfg, or completly remove the file if it was the only option
147+
- In setup.py:
148+
- Remove `extra_requires`
149+
- Add `python_requires=">=3.7",`
150+
- Remove the Python 2 and 3.5/3.6 classifiers
151+
- Add classifier `Programming Language :: Python :: 3 :: Only`
152+
- Remove the "azure" check if applicable (see next note)
153+
154+
# Note on checking old Azure packages
155+
156+
You may see code in `setup.py` looking like this:
157+
```python
158+
# azure v0.x is not compatible with this package
159+
# azure v0.x used to have a __version__ attribute (newer versions don't)
160+
try:
161+
import azure
162+
163+
try:
164+
VER = azure.__version__ # type: ignore
165+
raise Exception(
166+
"This package is incompatible with azure=={}. ".format(VER) + 'Uninstall it with "pip uninstall azure".'
167+
)
168+
except AttributeError:
169+
pass
170+
except ImportError:
171+
pass
172+
```
173+
174+
This was to prevent some difficult update scenario 6 years ago, and can be safely removed from your setup.py
175+
176+
# Note on Python 2
177+
178+
The "extras_requires" section MUST include a conditional dependency on "azure-nspkg" for Python 2. Example:
179+
180+
```python
181+
extras_require={
182+
":python_version<'3.0'": ['azure-nspkg'],
183+
}
184+
```
185+
186+
An additional verification is that wheels installs `azure-nskpg` ONLY on Python 2.

doc/dev/perfstress_tests.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ The framework has a series of common command line options built in:
8282
- `-w --warm-up=5` Number of seconds to spend warming up the connection before measuring begins. Default is 5.
8383
- `--sync` Whether to run the tests in sync or async. Default is False (async).
8484
- `--no-cleanup` Whether to keep newly created resources after test run. Default is False (resources will be deleted).
85-
- `-x --test-proxy` Whether to run the tests against the test proxy server. Specfiy the URL for the proxy endpoint (e.g. "https://localhost:5001").
85+
- `-x --test-proxies` Whether to run the tests against the test proxy server. Specify the URL(s) for the proxy endpoint(s) (e.g. "https://localhost:5001").
8686
- `--profile` Whether to run the perftest with cProfile. If enabled (default is False), the output file of the **last completed single iteration** will be written to the current working directory in the format `"cProfile-<TestClassName>-<TestID>-<sync/async>.pstats"`.
8787

8888

doc/dev/test_proxy_migration_guide.md

+50-8
Original file line numberDiff line numberDiff line change
@@ -28,25 +28,25 @@ class TestExample(AzureTestCase):
2828
### New test structure
2929

3030
To use the proxy, test classes should inherit from AzureRecordedTestCase and recorded test methods should use a
31-
RecordedByProxy decorator:
31+
`recorded_by_proxy` decorator:
3232

3333
```py
34-
from devtools_testutils import AzureRecordedTestCase, RecordedByProxy
34+
from devtools_testutils import AzureRecordedTestCase, recorded_by_proxy
3535

3636
class TestExample(AzureRecordedTestCase):
3737

38-
@RecordedByProxy
38+
@recorded_by_proxy
3939
def test_example(self):
4040
...
4141

4242
@ExamplePreparer()
43-
@RecordedByProxy
43+
@recorded_by_proxy
4444
def test_example_with_preparer(self):
4545
...
4646
```
4747

48-
For async tests, import the RecordedByProxyAsync decorator from `devtools_testutils.aio` and use it in the same
49-
way as RecordedByProxy.
48+
For async tests, import the `recorded_by_proxy_async` decorator from `devtools_testutils.aio` and use it in the same
49+
way as `recorded_by_proxy`.
5050

5151
> **Note:** since AzureRecordedTestCase doesn't inherit from `unittest.TestCase`, test class names need to start
5252
> with "Test" in order to be properly collected by pytest by default. For more information, please refer to
@@ -135,6 +135,48 @@ made to `https://fakeendpoint-secondary.table.core.windows.net`, and URIs will a
135135

136136
For more details about sanitizers and their options, please refer to [devtools_testutils/sanitizers.py][py_sanitizers].
137137

138+
### Enabling Testproxy on the CI
139+
140+
To enable test proxy on the CI, you need to set the parameter `TestProxy: true` on ci.yml and on tests.yml are present in the service level folder.
141+
142+
![image](https://user-images.githubusercontent.com/45376673/142270668-5be58bca-87e5-45f5-b593-44f8b1f757bc.png)
143+
### Record test variables
144+
145+
To run recorded tests successfully when there's an element of non-secret randomness to them, the test proxy provides a
146+
[`variables` API](https://github.com/Azure/azure-sdk-tools/tree/main/tools/test-proxy/Azure.Sdk.Tools.TestProxy#storing-variables).
147+
This makes it possible for a test to record the values of variables that were used during recording and use the same
148+
values in playback mode without a sanitizer.
149+
150+
For example, imagine that a test uses a randomized `table_name` variable when creating resources. The same random value
151+
for `table_name` can be used in playback mode by using this `variables` API.
152+
153+
There are two requirements for a test to use recorded variables. First, the test method should accept `**kwargs` and/or
154+
a `variables` parameter. Second, the test method should `return` a dictionary with any test variables that it wants to
155+
record. This dictionary will be stored in the recording when the test is run live, and will be passed to the test as a
156+
`variables` keyword argument when the test is run in playback.
157+
158+
Below is a code example of how a test method could use recorded variables:
159+
160+
```python
161+
from devtools_testutils import AzureRecordedTestCase, recorded_by_proxy
162+
163+
class TestExample(AzureRecordedTestCase):
164+
165+
@recorded_by_proxy
166+
def test_example(self, variables):
167+
# in live mode, variables is an empty dictionary
168+
# in playback mode, the value of variables is {"table_name": "random-value"}
169+
if self.is_live:
170+
table_name = "random-value"
171+
variables = {"table_name": table_name}
172+
173+
# use variables["table_name"] when using the table name throughout the test
174+
...
175+
176+
# return the variables at the end of the test
177+
return variables
178+
```
179+
138180
## Implementation details
139181

140182
### What does the test proxy do?
@@ -147,7 +189,7 @@ For example, if an operation would typically make a GET request to
147189
`https://localhost:5001/Tables` instead. The original endpoint should be stored in an `x-recording-upstream-base-uri` --
148190
the proxy will send the original request and record the result.
149191

150-
The RecordedByProxy and RecordedByProxyAsync decorators patch test requests to do this for you.
192+
The `recorded_by_proxy` and `recorded_by_proxy_async` decorators patch test requests to do this for you.
151193

152194
### How does the test proxy know when and what to record or play back?
153195

@@ -179,7 +221,7 @@ Running tests in playback follows the same pattern, except that requests will be
179221
`/playback/stop` instead. A header, `x-recording-mode`, should be set to `record` for all requests when recording and
180222
`playback` when playing recordings back. More details can be found [here][detailed_docs].
181223

182-
The RecordedByProxy and RecordedByProxyAsync decorators send the appropriate requests at the start and end of each test
224+
The `recorded_by_proxy` and `recorded_by_proxy_async` decorators send the appropriate requests at the start and end of each test
183225
case.
184226

185227
[detailed_docs]: https://github.com/Azure/azure-sdk-tools/tree/main/tools/test-proxy/Azure.Sdk.Tools.TestProxy/README.md

eng/common/TestResources/New-TestResources.ps1

+24-6
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,13 @@ if (!$PSBoundParameters.ContainsKey('ErrorAction')) {
8484
$ErrorActionPreference = 'Stop'
8585
}
8686

87-
function Log($Message) {
87+
function Log($Message)
88+
{
8889
Write-Host ('{0} - {1}' -f [DateTime]::Now.ToLongTimeString(), $Message)
8990
}
9091

91-
function Retry([scriptblock] $Action, [int] $Attempts = 5) {
92+
function Retry([scriptblock] $Action, [int] $Attempts = 5)
93+
{
9294
$attempt = 0
9395
$sleep = 5
9496

@@ -109,7 +111,20 @@ function Retry([scriptblock] $Action, [int] $Attempts = 5) {
109111
}
110112
}
111113

112-
function MergeHashes([hashtable] $source, [psvariable] $dest) {
114+
function LoadCloudConfig([string] $env)
115+
{
116+
$configPath = "$PSScriptRoot/clouds/$env.json"
117+
if (!(Test-Path $configPath)) {
118+
Write-Warning "Could not find cloud configuration for environment '$env'"
119+
return @{}
120+
}
121+
122+
$config = Get-Content $configPath | ConvertFrom-Json -AsHashtable
123+
return $config
124+
}
125+
126+
function MergeHashes([hashtable] $source, [psvariable] $dest)
127+
{
113128
foreach ($key in $source.Keys) {
114129
if ($dest.Value.ContainsKey($key) -and $dest.Value[$key] -ne $source[$key]) {
115130
Write-Warning ("Overwriting '$($dest.Name).$($key)' with value '$($dest.Value[$key])' " +
@@ -119,7 +134,8 @@ function MergeHashes([hashtable] $source, [psvariable] $dest) {
119134
}
120135
}
121136

122-
function BuildBicepFile([System.IO.FileSystemInfo] $file) {
137+
function BuildBicepFile([System.IO.FileSystemInfo] $file)
138+
{
123139
if (!(Get-Command bicep -ErrorAction Ignore)) {
124140
Write-Error "A bicep file was found at '$($file.FullName)' but the Azure Bicep CLI is not installed. See https://aka.ms/install-bicep-pwsh"
125141
throw
@@ -334,7 +350,7 @@ try {
334350
$serviceName = if (Split-Path $ServiceDirectory) {
335351
Split-Path -Leaf $ServiceDirectory
336352
} else {
337-
$ServiceDirectory
353+
$ServiceDirectory.Trim('/')
338354
}
339355

340356
$ResourceGroupName = if ($ResourceGroupName) {
@@ -492,6 +508,8 @@ try {
492508
$templateParameters.Add('testApplicationSecret', $TestApplicationSecret)
493509
}
494510

511+
$defaultCloudParameters = LoadCloudConfig $Environment
512+
MergeHashes $defaultCloudParameters $(Get-Variable templateParameters)
495513
MergeHashes $ArmTemplateParameters $(Get-Variable templateParameters)
496514
MergeHashes $AdditionalParameters $(Get-Variable templateParameters)
497515

@@ -600,7 +618,7 @@ try {
600618
$outputFile = "$($templateFile.originalFilePath).env"
601619

602620
$environmentText = $deploymentOutputs | ConvertTo-Json;
603-
$bytes = ([System.Text.Encoding]::UTF8).GetBytes($environmentText)
621+
$bytes = [System.Text.Encoding]::UTF8.GetBytes($environmentText)
604622
$protectedBytes = [Security.Cryptography.ProtectedData]::Protect($bytes, $null, [Security.Cryptography.DataProtectionScope]::CurrentUser)
605623

606624
Set-Content $outputFile -Value $protectedBytes -AsByteStream -Force

0 commit comments

Comments
 (0)