Skip to content

Commit 1b274b3

Browse files
authored
Releases v0.12.4 (#290)
1 parent ff39fc8 commit 1b274b3

38 files changed

+375
-327
lines changed

License

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Copyright 1999-2022 Alibaba Group Holding Ltd.
1+
Copyright 1999-2025 Alibaba Group Holding Ltd.
22

33

44
Apache License

README.md

Lines changed: 5 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
1-
# ODPS Python SDK and data analysis framework
1+
# ODPS Python SDK
22

3-
[![PyPI version](https://img.shields.io/pypi/v/pyodps.svg?style=flat-square)](https://pypi.python.org/pypi/pyodps) [![Docs](https://img.shields.io/badge/docs-latest-brightgreen.svg?style=flat-square)](http://pyodps.readthedocs.org/) [![License](https://img.shields.io/pypi/l/pyodps.svg?style=flat-square)](https://github.com/aliyun/aliyun-odps-python-sdk/blob/master/License) ![Implementation](https://img.shields.io/pypi/implementation/pyodps.svg?style=flat-square)
4-
5-
<div align="center">
6-
<img src="http://pyodps.readthedocs.org/zh_CN/latest/_static/PyODPS.png"><br><br>
7-
</div>
83
-----------------
94

105
Elegent way to access ODPS API. [Documentation](http://pyodps.readthedocs.org/)
@@ -49,12 +44,12 @@ $ pip install git+https://github.com/aliyun/aliyun-odps-python-sdk.git
4944
```python
5045
>>> import os
5146
>>> from odps import ODPS
52-
>>> # Make sure environment variable ALIBABA_CLOUD_ACCESS_KEY_ID already set to Access Key ID of user
53-
>>> # while environment variable ALIBABA_CLOUD_ACCESS_KEY_SECRET set to Access Key Secret of user.
47+
>>> # Make sure environment variable CLOUD_ACCESS_KEY_ID already set to Access Key ID of user
48+
>>> # while environment variable CLOUD_ACCESS_KEY_SECRET set to Access Key Secret of user.
5449
>>> # Not recommended to hardcode Access Key ID or Access Key Secret in your code.
5550
>>> o = ODPS(
56-
>>> os.getenv('ALIBABA_CLOUD_ACCESS_KEY_ID'),
57-
>>> os.getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET'),
51+
>>> os.getenv('CLOUD_ACCESS_KEY_ID'),
52+
>>> os.getenv('CLOUD_ACCESS_KEY_SECRET'),
5853
>>> project='**your-project**',
5954
>>> endpoint='**your-endpoint**',
6055
>>> )
@@ -93,37 +88,6 @@ False
9388
<column c_datetime_b, type datetime>]
9489
```
9590

96-
## DataFrame API
97-
98-
```python
99-
>>> from odps.df import DataFrame
100-
>>> df = DataFrame(o.get_table('pyodps_iris'))
101-
>>> df.dtypes
102-
odps.Schema {
103-
sepallength float64
104-
sepalwidth float64
105-
petallength float64
106-
petalwidth float64
107-
name string
108-
}
109-
>>> df.head(5)
110-
|==========================================| 1 / 1 (100.00%) 0s
111-
sepallength sepalwidth petallength petalwidth name
112-
0 5.1 3.5 1.4 0.2 Iris-setosa
113-
1 4.9 3.0 1.4 0.2 Iris-setosa
114-
2 4.7 3.2 1.3 0.2 Iris-setosa
115-
3 4.6 3.1 1.5 0.2 Iris-setosa
116-
4 5.0 3.6 1.4 0.2 Iris-setosa
117-
>>> df[df.sepalwidth > 3]['name', 'sepalwidth'].head(5)
118-
|==========================================| 1 / 1 (100.00%) 12s
119-
name sepalwidth
120-
0 Iris-setosa 3.5
121-
1 Iris-setosa 3.2
122-
2 Iris-setosa 3.1
123-
3 Iris-setosa 3.6
124-
4 Iris-setosa 3.9
125-
```
126-
12791
## Command-line and IPython enhancement
12892

12993
```
@@ -174,14 +138,6 @@ cd pyodps
174138
pip install -r requirements.txt -e .
175139
```
176140

177-
If you need to modify the frontend code, you need to install [nodejs/npm](https://www.npmjs.com/). To build and
178-
install your frontend code, use
179-
180-
```
181-
python setup.py build_js
182-
python setup.py install_js
183-
```
184-
185141
## License
186142

187143
Licensed under the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0.html)

README.rst

Lines changed: 7 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
ODPS Python SDK and data analysis framework
2-
===========================================
1+
ODPS Python SDK
2+
===============
33

4-
|PyPI version| |Docs| |License| |Implementation|
4+
--------------
55

66
Elegent way to access ODPS API.
77
`Documentation <http://pyodps.readthedocs.org/>`__
@@ -52,12 +52,12 @@ Usage
5252
5353
>>> import os
5454
>>> from odps import ODPS
55-
>>> # Make sure environment variable ALIBABA_CLOUD_ACCESS_KEY_ID already set to Access Key ID of user
56-
>>> # while environment variable ALIBABA_CLOUD_ACCESS_KEY_SECRET set to Access Key Secret of user.
55+
>>> # Make sure environment variable CLOUD_ACCESS_KEY_ID already set to Access Key ID of user
56+
>>> # while environment variable CLOUD_ACCESS_KEY_SECRET set to Access Key Secret of user.
5757
>>> # Not recommended to hardcode Access Key ID or Access Key Secret in your code.
5858
>>> o = ODPS(
59-
>>> os.getenv('ALIBABA_CLOUD_ACCESS_KEY_ID'),
60-
>>> os.getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET'),
59+
>>> os.getenv('CLOUD_ACCESS_KEY_ID'),
60+
>>> os.getenv('CLOUD_ACCESS_KEY_SECRET'),
6161
>>> project='**your-project**',
6262
>>> endpoint='**your-endpoint**',
6363
>>> )
@@ -95,38 +95,6 @@ Usage
9595
<column c_datetime_a, type datetime>,
9696
<column c_datetime_b, type datetime>]
9797
98-
DataFrame API
99-
-------------
100-
101-
.. code:: python
102-
103-
>>> from odps.df import DataFrame
104-
>>> df = DataFrame(o.get_table('pyodps_iris'))
105-
>>> df.dtypes
106-
odps.Schema {
107-
sepallength float64
108-
sepalwidth float64
109-
petallength float64
110-
petalwidth float64
111-
name string
112-
}
113-
>>> df.head(5)
114-
|==========================================| 1 / 1 (100.00%) 0s
115-
sepallength sepalwidth petallength petalwidth name
116-
0 5.1 3.5 1.4 0.2 Iris-setosa
117-
1 4.9 3.0 1.4 0.2 Iris-setosa
118-
2 4.7 3.2 1.3 0.2 Iris-setosa
119-
3 4.6 3.1 1.5 0.2 Iris-setosa
120-
4 5.0 3.6 1.4 0.2 Iris-setosa
121-
>>> df[df.sepalwidth > 3]['name', 'sepalwidth'].head(5)
122-
|==========================================| 1 / 1 (100.00%) 12s
123-
name sepalwidth
124-
0 Iris-setosa 3.5
125-
1 Iris-setosa 3.2
126-
2 Iris-setosa 3.1
127-
3 Iris-setosa 3.6
128-
4 Iris-setosa 3.9
129-
13098
Command-line and IPython enhancement
13199
------------------------------------
132100

@@ -181,25 +149,8 @@ source:
181149
cd pyodps
182150
pip install -r requirements.txt -e .
183151

184-
If you need to modify the frontend code, you need to install
185-
`nodejs/npm <https://www.npmjs.com/>`__. To build and install your
186-
frontend code, use
187-
188-
::
189-
190-
python setup.py build_js
191-
python setup.py install_js
192-
193152
License
194153
-------
195154

196155
Licensed under the `Apache License
197156
2.0 <https://www.apache.org/licenses/LICENSE-2.0.html>`__
198-
199-
.. |PyPI version| image:: https://img.shields.io/pypi/v/pyodps.svg?style=flat-square
200-
:target: https://pypi.python.org/pypi/pyodps
201-
.. |Docs| image:: https://img.shields.io/badge/docs-latest-brightgreen.svg?style=flat-square
202-
:target: http://pyodps.readthedocs.org/
203-
.. |License| image:: https://img.shields.io/pypi/l/pyodps.svg?style=flat-square
204-
:target: https://github.com/aliyun/aliyun-odps-python-sdk/blob/master/License
205-
.. |Implementation| image:: https://img.shields.io/pypi/implementation/pyodps.svg?style=flat-square

examples/storage_api/util.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 1999-2022 Alibaba Group Holding Ltd.
1+
# Copyright 1999-2025 Alibaba Group Holding Ltd.
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.
@@ -18,8 +18,8 @@
1818
from odps.apis.storage_api import *
1919

2020
o = ODPS(
21-
os.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"),
22-
os.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"),
21+
os.getenv("CLOUD_ACCESS_KEY_ID"),
22+
os.getenv("CLOUD_ACCESS_KEY_SECRET"),
2323
project="your-default-project",
2424
endpoint="your-end-point",
2525
)

odps/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
version_info = (0, 12, 4, "b1")
15+
version_info = (0, 12, 4)
1616
_num_index = max(idx if isinstance(v, int) else 0 for idx, v in enumerate(version_info))
1717
__version__ = ".".join(map(str, version_info[: _num_index + 1])) + "".join(
1818
version_info[_num_index + 1 :]

odps/accounts.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ def _get_v4_signature_key(self, date_str, region_name):
116116

117117
sig_prefix = _get_v4_signature_prefix()
118118

119-
k_secret = utils.to_binary(sig_prefix + self.secret_access_key)
119+
k_secret = utils.to_binary(sig_prefix + utils.to_str(self.secret_access_key))
120120
k_date = hmac.new(k_secret, utils.to_binary(date_str), hashlib.sha256).digest()
121121
k_region = hmac.new(
122122
k_date, utils.to_binary(region_name), hashlib.sha256
@@ -184,9 +184,10 @@ def sign_request(self, req, endpoint, region_name=None):
184184
hashlib.sha1,
185185
).digest()
186186
)
187+
provider = _get_v4_signature_prefix().rsplit("_", 1)[0]
187188
app_auth_str = (
188189
"account_provider:%s,signature_method:%s,access_id:%s,signature:%s"
189-
% ("aliyun", "hmac-sha1", self.access_id, utils.to_str(signature))
190+
% (provider, "hmac-sha1", self.access_id, utils.to_str(signature))
190191
)
191192
req.headers["application-authentication"] = app_auth_str
192193
logger.debug("headers after app signing: %r", req.headers)

odps/compat.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -334,11 +334,9 @@ def dst(self, dt):
334334

335335

336336
try:
337-
import zoneinfo
338-
339-
utc = zoneinfo.ZoneInfo("UTC")
337+
utc = datetime.timezone.utc
340338
FixedOffset = _FixedOffset
341-
except ImportError:
339+
except AttributeError:
342340
try:
343341
import pytz
344342

odps/core.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
DEFAULT_ENDPOINT = "http://service.odps.aliyun.com/api"
3030
DEFAULT_REGION_NAME = "cn"
3131
LOGVIEW_HOST_DEFAULT = "http://logview.aliyun.com"
32-
JOB_INSIGHT_HOST_DEFAULT = "https://maxcompute.console.aliyun.com"
3332

3433
_ALTER_TABLE_REGEX = re.compile(
3534
r"^\s*(drop|alter)\s+table\s*(|if\s+exists)\s+(?P<table_name>[^\s;]+)", re.I
@@ -2164,22 +2163,22 @@ def get_job_insight_host(self):
21642163

21652164
job_insight_released = utils.is_job_insight_released(self.endpoint)
21662165
# when use_legacy_logview is enforced as False, we still use job insight
2167-
if job_insight_released is False and options.use_legacy_logview is not False:
2166+
if not job_insight_released and options.use_legacy_logview is not False:
21682167
return None
21692168

2169+
jobinsight_host = self._get_job_insight_from_request()
2170+
if jobinsight_host:
2171+
_jobinsight_host_cache[self.endpoint] = jobinsight_host
2172+
return jobinsight_host
2173+
2174+
def _get_job_insight_from_request(self):
21702175
try:
21712176
jobinsight_host = utils.to_str(
21722177
self.rest.get(self.endpoint + "/webconsole/host").content
21732178
)
2174-
jobinsight_host = jobinsight_host.strip() or None
2179+
return jobinsight_host.strip() or None
21752180
except:
2176-
jobinsight_host = None
2177-
if not jobinsight_host and job_insight_released is True:
2178-
jobinsight_host = JOB_INSIGHT_HOST_DEFAULT
2179-
2180-
if jobinsight_host:
2181-
_jobinsight_host_cache[self.endpoint] = jobinsight_host
2182-
return jobinsight_host
2181+
return None
21832182

21842183
def get_logview_address(
21852184
self, instance_id, hours=None, project=None, use_legacy=None

odps/dbapi.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
# See the License for the specific language governing permissions and
1515
# limitations under the License.
1616

17+
import base64
1718
import functools
1819
import warnings
1920

@@ -40,6 +41,14 @@ class State(enum.Enum):
4041
FINISHED = 2
4142

4243

44+
class Binary(object):
45+
def __init__(self, value):
46+
self.value = value
47+
48+
def __str__(self):
49+
return "unbase64('%s')" % base64.b64encode(self.value).decode()
50+
51+
4352
def connect(*args, **kwargs):
4453
"""Constructor for creating a connection to the database. See class :py:class:`Connection` for
4554
arguments.

odps/df/backends/pd/tests/test_engine.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2677,6 +2677,7 @@ def persist_with_dyna_part_test(table_name):
26772677
base_table_name = tn('pyodps_test_pd_engine_persist_table')
26782678
try:
26792679
options.tunnel.write_row_batch_size = 1
2680+
options.df.writer_count_limit = 2
26802681
run_sub_tests_in_parallel(
26812682
10,
26822683
[
@@ -2686,6 +2687,7 @@ def persist_with_dyna_part_test(table_name):
26862687
)
26872688
finally:
26882689
options.tunnel.write_row_batch_size = 1024
2690+
options.df.writer_count_limit = 50
26892691

26902692

26912693
def test_append_id(odps, setup):

0 commit comments

Comments
 (0)