Skip to content

Commit ab2b0ea

Browse files
authored
[Cosmos] Remove support for Python27, set Python36 as minimum, and update cosmos emulator pipeline (#22475)
* removed six package and updated packaging/ documentation to reflect new standards * massive oops, will rotate keys * change 3.7 to 3.6 * pylint * addressed Anna's comments
1 parent 113291b commit ab2b0ea

25 files changed

+119
-176
lines changed

eng/pipelines/templates/stages/cosmos-sdk-client.yml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,9 @@ stages:
3333
- job: Emulator
3434
strategy:
3535
matrix:
36-
Windows_Python35:
36+
Windows_Python36:
3737
OSVmImage: 'windows-2019'
38-
PythonVersion: '3.5'
39-
Windows_Python27:
40-
OSVmImage: 'windows-2019'
41-
PythonVersion: '2.7'
38+
PythonVersion: '3.6'
4239
pool:
4340
vmImage: $(OSVmImage)
4441

sdk/cosmos/azure-cosmos/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
### 4.3.0b2 (Unreleased)
44

5+
This version and all future versions will require Python 3.6+. Python 2.7 is no longer supported.
6+
We will also be removing support for Python 3.6 and will only support Python 3.7+ starting December 2022.
7+
58
#### Features Added
69

710
#### Breaking Changes

sdk/cosmos/azure-cosmos/MANIFEST.in

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
include README.md
2-
include CHANGELOG.md
1+
include *.md
32
include LICENSE
43
include azure/__init__.py
5-
recursive-include samples *.py
4+
recursive-include samples *.py *.md
65
recursive-include test *.py
7-
recursive-include doc *.rst
86
include azure/cosmos/py.typed

sdk/cosmos/azure-cosmos/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## _Disclaimer_
2+
_Azure SDK Python packages support for Python 2.7 has ended 01 January 2022. For more information and questions, please refer to https://github.com/Azure/azure-sdk-for-python/issues/20691_
3+
14
# Azure Cosmos DB SQL API client library for Python
25

36
Azure Cosmos DB is a globally distributed, multi-model database service that supports document, key-value, wide-column, and graph databases.
@@ -23,7 +26,7 @@ New releases of this SDK won't support Python 2.x starting January 1st, 2022. Pl
2326

2427
* Azure subscription - [Create a free account][azure_sub]
2528
* Azure [Cosmos DB account][cosmos_account] - SQL API
26-
* [Python 2.7 or 3.6+][python]
29+
* [Python 3.6+][python]
2730

2831
If you need a Cosmos DB SQL API account, you can create one with this [Azure CLI][azure_cli] command:
2932

sdk/cosmos/azure-cosmos/azure/cosmos/_base.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@
2929
import binascii
3030
from typing import Dict, Any
3131

32-
import six
33-
from six.moves.urllib.parse import quote as urllib_quote
32+
from urllib.parse import quote as urllib_quote
3433

3534
from azure.core import MatchConditions
3635

@@ -578,9 +577,6 @@ def IsValidBase64String(string_to_validate):
578577
if len(buffer) != 4:
579578
return False
580579
except Exception as e: # pylint: disable=broad-except
581-
if six.PY2:
582-
e = e.message # pylint: disable=no-member
583-
# (e.message does exist on py2)
584580
if isinstance(e, binascii.Error):
585581
return False
586582
raise e

sdk/cosmos/azure-cosmos/azure/cosmos/_cosmos_client_connection.py

Lines changed: 53 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
"""
2727
# https://github.com/PyCQA/pylint/issues/3112
2828
# Currently pylint is locked to 2.3.3 and this is fixed in 2.4.4
29-
from typing import Dict, Any, Optional # pylint: disable=unused-import
30-
import six
29+
from typing import Dict, Any, Optional # pylint: disable=unused-import
30+
import urllib.parse
3131
from urllib3.util.retry import Retry
3232
from azure.core.paging import ItemPaged # type: ignore
3333
from azure.core import PipelineClient # type: ignore
@@ -59,6 +59,7 @@
5959
from . import _utils
6060
from .partition_key import _Undefined, _Empty
6161

62+
6263
# pylint: disable=protected-access
6364

6465

@@ -87,12 +88,12 @@ class _QueryCompatibilityMode:
8788
_DefaultStringRangePrecision = -1
8889

8990
def __init__(
90-
self,
91-
url_connection, # type: str
92-
auth, # type: Dict[str, Any]
93-
connection_policy=None, # type: Optional[ConnectionPolicy]
94-
consistency_level=documents.ConsistencyLevel.Session, # type: str
95-
**kwargs # type: Any
91+
self,
92+
url_connection, # type: str
93+
auth, # type: Dict[str, Any]
94+
connection_policy=None, # type: Optional[ConnectionPolicy]
95+
consistency_level=documents.ConsistencyLevel.Session, # type: str
96+
**kwargs # type: Any
9697
):
9798
# type: (...) -> None
9899
"""
@@ -177,9 +178,9 @@ def __init__(
177178
proxies = kwargs.pop('proxies', {})
178179
if self.connection_policy.ProxyConfiguration and self.connection_policy.ProxyConfiguration.Host:
179180
host = self.connection_policy.ProxyConfiguration.Host
180-
url = six.moves.urllib.parse.urlparse(host)
181+
url = urllib.parse.urlparse(host)
181182
proxy = host if url.port else host + ":" + str(self.connection_policy.ProxyConfiguration.Port)
182-
proxies.update({url.scheme : proxy})
183+
proxies.update({url.scheme: proxy})
183184

184185
policies = [
185186
HeadersPolicy(**kwargs),
@@ -191,7 +192,7 @@ def __init__(
191192
NetworkTraceLoggingPolicy(**kwargs),
192193
DistributedTracingPolicy(**kwargs),
193194
HttpLoggingPolicy(**kwargs),
194-
]
195+
]
195196

196197
transport = kwargs.pop("transport", None)
197198
self.pipeline_client = PipelineClient(base_url=url_connection, transport=transport, policies=policies)
@@ -840,13 +841,13 @@ def ReadItems(self, collection_link, feed_options=None, response_hook=None, **kw
840841
return self.QueryItems(collection_link, None, feed_options, response_hook=response_hook, **kwargs)
841842

842843
def QueryItems(
843-
self,
844-
database_or_container_link,
845-
query,
846-
options=None,
847-
partition_key=None,
848-
response_hook=None,
849-
**kwargs
844+
self,
845+
database_or_container_link,
846+
query,
847+
options=None,
848+
partition_key=None,
849+
response_hook=None,
850+
**kwargs
850851
):
851852
"""Queries documents in a collection.
852853
@@ -936,7 +937,8 @@ def QueryItemsChangeFeed(self, collection_link, options=None, response_hook=None
936937
)
937938

938939
def _QueryChangeFeed(
939-
self, collection_link, resource_type, options=None, partition_key_range_id=None, response_hook=None, **kwargs
940+
self, collection_link, resource_type, options=None, partition_key_range_id=None, response_hook=None,
941+
**kwargs
940942
):
941943
"""Queries change feed of a resource in a collection.
942944
@@ -1129,10 +1131,10 @@ def UpsertItem(self, database_or_container_link, document, options=None, **kwarg
11291131
return self.Upsert(document, path, "docs", collection_id, None, options, **kwargs)
11301132

11311133
PartitionResolverErrorMessage = (
1132-
"Couldn't find any partition resolvers for the database link provided. "
1133-
+ "Ensure that the link you used when registering the partition resolvers "
1134-
+ "matches the link provided or you need to register both types of database "
1135-
+ "link(self link as well as ID based link)."
1134+
"Couldn't find any partition resolvers for the database link provided. "
1135+
+ "Ensure that the link you used when registering the partition resolvers "
1136+
+ "matches the link provided or you need to register both types of database "
1137+
+ "link(self link as well as ID based link)."
11361138
)
11371139

11381140
# Gets the collection id and path for the document
@@ -2040,7 +2042,7 @@ def GetDatabaseAccount(self, url_connection=None, **kwargs):
20402042
]
20412043

20422044
self._useMultipleWriteLocations = (
2043-
self.connection_policy.UseMultipleWriteLocations and database_account._EnableMultipleWritableLocations
2045+
self.connection_policy.UseMultipleWriteLocations and database_account._EnableMultipleWritableLocations
20442046
)
20452047
return database_account
20462048

@@ -2107,7 +2109,8 @@ def Upsert(self, body, path, typ, id, initial_headers, options=None, **kwargs):
21072109
self._UpdateSessionIfRequired(headers, result, self.last_response_headers)
21082110
return result
21092111

2110-
def Replace(self, resource, path, typ, id, initial_headers, options=None, **kwargs): # pylint: disable=redefined-builtin
2112+
def Replace(self, resource, path, typ, id, initial_headers, options=None,
2113+
**kwargs): # pylint: disable=redefined-builtin
21112114
"""Replaces a Azure Cosmos resource and returns it.
21122115
21132116
:param dict resource:
@@ -2163,7 +2166,8 @@ def Read(self, path, typ, id, initial_headers, options=None, **kwargs): # pylin
21632166
result, self.last_response_headers = self.__Get(path, request_params, headers, **kwargs)
21642167
return result
21652168

2166-
def DeleteResource(self, path, typ, id, initial_headers, options=None, **kwargs): # pylint: disable=redefined-builtin
2169+
def DeleteResource(self, path, typ, id, initial_headers, options=None,
2170+
**kwargs): # pylint: disable=redefined-builtin
21672171
"""Deletes a Azure Cosmos resource and returns it.
21682172
21692173
:param str path:
@@ -2327,18 +2331,18 @@ def QueryFeed(self, path, collection_id, query, options, partition_key_range_id=
23272331
)
23282332

23292333
def __QueryFeed(
2330-
self,
2331-
path,
2332-
typ,
2333-
id_,
2334-
result_fn,
2335-
create_fn,
2336-
query,
2337-
options=None,
2338-
partition_key_range_id=None,
2339-
response_hook=None,
2340-
is_query_plan=False,
2341-
**kwargs
2334+
self,
2335+
path,
2336+
typ,
2337+
id_,
2338+
result_fn,
2339+
create_fn,
2340+
query,
2341+
options=None,
2342+
partition_key_range_id=None,
2343+
response_hook=None,
2344+
is_query_plan=False,
2345+
**kwargs
23422346
):
23432347
"""Query for more than one Azure Cosmos resources.
23442348
@@ -2380,8 +2384,8 @@ def __GetBodiesFromQueryResult(result):
23802384
# Copy to make sure that default_headers won't be changed.
23812385
if query is None:
23822386
# Query operations will use ReadEndpoint even though it uses GET(for feed requests)
2383-
request_params = _request_object.RequestObject(typ,
2384-
documents._OperationType.QueryPlan if is_query_plan else documents._OperationType.ReadFeed)
2387+
request_params = _request_object.RequestObject(
2388+
typ, documents._OperationType.QueryPlan if is_query_plan else documents._OperationType.ReadFeed)
23852389
headers = base.GetHeaders(self, initial_headers, "get", path, id_, typ, options, partition_key_range_id)
23862390
result, self.last_response_headers = self.__Get(path, request_params, headers, **kwargs)
23872391
if response_hook:
@@ -2395,8 +2399,8 @@ def __GetBodiesFromQueryResult(result):
23952399
initial_headers[http_constants.HttpHeaders.IsQuery] = "true"
23962400

23972401
if (
2398-
self._query_compatibility_mode == CosmosClientConnection._QueryCompatibilityMode.Default
2399-
or self._query_compatibility_mode == CosmosClientConnection._QueryCompatibilityMode.Query
2402+
self._query_compatibility_mode == CosmosClientConnection._QueryCompatibilityMode.Default
2403+
or self._query_compatibility_mode == CosmosClientConnection._QueryCompatibilityMode.Query
24002404
):
24012405
initial_headers[http_constants.HttpHeaders.ContentType] = runtime_constants.MediaTypes.QueryJson
24022406
elif self._query_compatibility_mode == CosmosClientConnection._QueryCompatibilityMode.SqlQuery:
@@ -2428,7 +2432,7 @@ def _GetQueryPlanThroughGateway(self, query, resource_link, **kwargs):
24282432
"isQueryPlanRequest": True,
24292433
"supportedQueryFeatures": supported_query_features,
24302434
"queryVersion": http_constants.Versions.QueryVersion
2431-
}
2435+
}
24322436

24332437
resource_link = base.TrimBeginningAndEndingSlashes(resource_link)
24342438
path = base.GetPathFromLink(resource_link, "docs")
@@ -2459,18 +2463,18 @@ def __CheckAndUnifyQueryFormat(self, query_body):
24592463
dict or string
24602464
"""
24612465
if (
2462-
self._query_compatibility_mode == CosmosClientConnection._QueryCompatibilityMode.Default
2463-
or self._query_compatibility_mode == CosmosClientConnection._QueryCompatibilityMode.Query
2466+
self._query_compatibility_mode == CosmosClientConnection._QueryCompatibilityMode.Default
2467+
or self._query_compatibility_mode == CosmosClientConnection._QueryCompatibilityMode.Query
24642468
):
2465-
if not isinstance(query_body, dict) and not isinstance(query_body, six.string_types):
2469+
if not isinstance(query_body, dict) and not isinstance(query_body, str):
24662470
raise TypeError("query body must be a dict or string.")
24672471
if isinstance(query_body, dict) and not query_body.get("query"):
24682472
raise ValueError('query body must have valid query text with key "query".')
2469-
if isinstance(query_body, six.string_types):
2473+
if isinstance(query_body, str):
24702474
return {"query": query_body}
24712475
elif (
2472-
self._query_compatibility_mode == CosmosClientConnection._QueryCompatibilityMode.SqlQuery
2473-
and not isinstance(query_body, six.string_types)
2476+
self._query_compatibility_mode == CosmosClientConnection._QueryCompatibilityMode.SqlQuery
2477+
and not isinstance(query_body, str)
24742478
):
24752479
raise TypeError("query body must be a string.")
24762480
else:

sdk/cosmos/azure-cosmos/azure/cosmos/_execution_context/document_producer.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@
2626
import numbers
2727
from collections import deque
2828

29-
import six
30-
3129
from azure.cosmos import _base
3230
from azure.cosmos._execution_context.base_execution_context import _DefaultQueryExecutionContext
3331

@@ -154,7 +152,7 @@ def getTypeOrd(orderby_item):
154152
return 2
155153
if isinstance(val, numbers.Number):
156154
return 4
157-
if isinstance(val, six.string_types):
155+
if isinstance(val, str):
158156
return 5
159157

160158
raise TypeError("unknown type" + str(val))
@@ -176,7 +174,7 @@ def getTypeStr(orderby_item):
176174
return "Boolean"
177175
if isinstance(val, numbers.Number):
178176
return "Number"
179-
if isinstance(val, six.string_types):
177+
if isinstance(val, str):
180178
return "String"
181179

182180
raise TypeError("unknown type" + str(val))

sdk/cosmos/azure-cosmos/azure/cosmos/_execution_context/endpoint_component.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import copy
2727
import hashlib
2828
import json
29-
import six
3029

3130
from azure.cosmos._execution_context.aggregators import (
3231
_AverageAggregator,
@@ -127,17 +126,15 @@ def __next__(self):
127126
res = next(self._execution_context)
128127

129128
json_repr = json.dumps(self.make_hash(res))
130-
if six.PY3:
131-
json_repr = json_repr.encode("utf-8")
129+
json_repr = json_repr.encode("utf-8")
132130

133131
hash_object = hashlib.sha1(json_repr) # nosec
134132
hashed_result = hash_object.hexdigest()
135133

136134
while hashed_result in self.last_result:
137135
res = next(self._execution_context)
138136
json_repr = json.dumps(self.make_hash(res))
139-
if six.PY3:
140-
json_repr = json_repr.encode("utf-8")
137+
json_repr = json_repr.encode("utf-8")
141138

142139
hash_object = hashlib.sha1(json_repr) # nosec
143140
hashed_result = hash_object.hexdigest()

sdk/cosmos/azure-cosmos/azure/cosmos/_execution_context/query_execution_info.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
"""Internal class for partitioned query execution info implementation in the Azure Cosmos database service.
2323
"""
2424

25-
import six
2625
from azure.cosmos.documents import _DistinctType
2726

2827

@@ -121,7 +120,7 @@ def has_rewritten_query(self):
121120
def _extract(self, path):
122121

123122
item = self._query_execution_info
124-
if isinstance(path, six.string_types):
123+
if isinstance(path, str):
125124
return item.get(path)
126125

127126
for p in path:

0 commit comments

Comments
 (0)