Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix upload config compatibility and improve test cases #447

Merged
merged 7 commits into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions .github/workflows/ci-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,24 +35,37 @@ jobs:
wget -qLO get-pip.py "$PIP_BOOTSTRAP_SCRIPT_PREFIX/$MAJOR.$MINOR/get-pip.py"
python get-pip.py --user
fi
- name: Setup mock server
shell: bash -el {0}
run: |
conda create -y -n mock-server python=3.10
conda activate mock-server
python3 --version
nohup python3 tests/mock_server/main.py --port 9000 > py-mock-server.log &
echo $! > mock-server.pid
conda deactivate
- name: Install dependencies
shell: bash -l {0}
run: |
python -m pip install --upgrade pip
python -m pip install -I -e ".[dev]"
- name: Run cases
shell: bash -l {0}
shell: bash -el {0}
env:
QINIU_ACCESS_KEY: ${{ secrets.QINIU_ACCESS_KEY }}
QINIU_SECRET_KEY: ${{ secrets.QINIU_SECRET_KEY }}
QINIU_TEST_BUCKET: ${{ secrets.QINIU_TEST_BUCKET }}
QINIU_TEST_DOMAIN: ${{ secrets.QINIU_TEST_DOMAIN }}
QINIU_TEST_ENV: "travis"
MOCK_SERVER_ADDRESS: "http://127.0.0.1:9000"
PYTHONPATH: "$PYTHONPATH:."
run: |
set -e
flake8 --show-source --max-line-length=160 .
py.test --cov qiniu
flake8 --show-source --max-line-length=160 ./qiniu
coverage run -m pytest ./test_qiniu.py ./tests/cases
ocular --data-file .coverage
coverage run test_qiniu.py
codecov
cat mock-server.pid | xargs kill
- name: Print mock server log
if: ${{ failure() }}
run: |
cat py-mock-server.log
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# Changelog
## 7.13.1(2024-02-04)
* 对象存储,修复上传部分配置项的兼容

## 7.13.0(2023-12-11)
* 对象存储,新增支持归档直读存储
* 对象存储,批量操作支持自动查询 rs 服务域名
Expand Down
2 changes: 1 addition & 1 deletion qiniu/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

# flake8: noqa

__version__ = '7.13.0'
__version__ = '7.13.1'

from .auth import Auth, QiniuMacAuth

Expand Down
3 changes: 2 additions & 1 deletion qiniu/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
# ---------

if is_py2:
from urllib import urlencode # noqa
from urlparse import urlparse # noqa
import StringIO
StringIO = BytesIO = StringIO.StringIO
Expand Down Expand Up @@ -60,7 +61,7 @@ def is_seekable(data):
return False

elif is_py3:
from urllib.parse import urlparse # noqa
from urllib.parse import urlparse, urlencode # noqa
import io
StringIO = io.StringIO
BytesIO = io.BytesIO
Expand Down
14 changes: 14 additions & 0 deletions qiniu/http/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
import logging
import platform
import functools

import requests
from requests.adapters import HTTPAdapter
Expand All @@ -21,6 +22,19 @@
)


# compatibility with some config from qiniu.config
def _before_send(func):
@functools.wraps(func)
def wrapper(self, *args, **kwargs):
if _session is None:
_init()
return func(self, *args, **kwargs)

return wrapper


qn_http_client.send_request = _before_send(qn_http_client.send_request)

_sys_info = '{0}; {1}'.format(platform.system(), platform.machine())
_python_ver = platform.python_version()

Expand Down
4 changes: 4 additions & 0 deletions qiniu/http/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import requests

from qiniu.config import get_default
from .response import ResponseInfo
from .middleware import compose_middleware

Expand All @@ -14,6 +15,9 @@ def __init__(self, middlewares=None, send_opts=None):
self.send_opts = {} if send_opts is None else send_opts

def _wrap_send(self, req, **kwargs):
# compatibility with setting timeout by qiniu.config.set_default
kwargs.setdefault('timeout', get_default('connection_timeout'))

resp = self.session.send(req.prepare(), **kwargs)
return ResponseInfo(resp, None)

Expand Down
8 changes: 7 additions & 1 deletion qiniu/http/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,13 @@ def ok(self):
return self.status_code // 100 == 2

def need_retry(self):
if 0 < self.status_code < 500:
if 100 <= self.status_code < 500:
return False
if all([
self.status_code < 0,
self.exception is not None,
'BadStatusLine' in str(self.exception)
]):
return False
# https://developer.qiniu.com/fusion/kb/1352/the-http-request-return-a-status-code
if self.status_code in [
Expand Down
2 changes: 2 additions & 0 deletions qiniu/services/storage/uploaders/abc/resume_uploader_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ def initial_parts(
data_size,
modify_time,
part_size,
file_name,
**kwargs
):
"""
Expand All @@ -157,6 +158,7 @@ def initial_parts(
data_size: int
modify_time: int
part_size: int
file_name: str
kwargs: dict

Returns
Expand Down
14 changes: 9 additions & 5 deletions qiniu/services/storage/uploaders/abc/uploader_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ def _get_regions(self):
if self.regions:
return self.regions

# handle compatibility for default_zone
default_region = config.get_default('default_zone')
if default_region:
self.regions = [default_region]
Expand All @@ -108,11 +109,14 @@ def _get_up_hosts(self, access_key=None):
if not regions:
raise ValueError('No region available.')

if regions[0].up_host and regions[0].up_host_backup:
return [
regions[0].up_host,
regions[0].up_host_backup
]
# get up hosts in region
up_hosts = [
regions[0].up_host,
regions[0].up_host_backup
]
up_hosts = [h for h in up_hosts if h]
if up_hosts:
return up_hosts

# this is correct, it does return hosts. bad function name by legacy
return regions[0].get_up_host(
Expand Down
18 changes: 15 additions & 3 deletions qiniu/services/storage/uploaders/resume_uploader_v1.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import logging
import math
from collections import namedtuple
from concurrent import futures
from io import BytesIO
Expand Down Expand Up @@ -65,7 +66,11 @@ def _recover_from_record(
record_context = [
ctx
for ctx in record_context
if ctx.get('expired_at', 0) > now
if (
ctx.get('expired_at', 0) > now and
ctx.get('part_no', None) and
ctx.get('ctx', None)
)
]

# assign to context
Expand Down Expand Up @@ -173,6 +178,7 @@ def initial_parts(
data=None,
modify_time=None,
data_size=None,
file_name=None,
**kwargs
):
"""
Expand All @@ -184,6 +190,7 @@ def initial_parts(
data
modify_time
data_size
file_name

kwargs

Expand Down Expand Up @@ -222,7 +229,8 @@ def initial_parts(
)

# try to recover from record
file_name = path.basename(file_path) if file_path else None
if not file_name and file_path:
file_name = path.basename(file_path)
context = self._recover_from_record(
file_name,
key,
Expand Down Expand Up @@ -275,7 +283,10 @@ def upload_parts(

# initial upload state
part, resp = None, None
uploaded_size = 0
uploaded_size = context.part_size * len(context.parts)
if math.ceil(data_size / context.part_size) in [p.part_no for p in context.parts]:
# if last part uploaded, should correct the uploaded size
uploaded_size += (data_size % context.part_size) - context.part_size
lock = Lock()

if not self.concurrent_executor:
Expand Down Expand Up @@ -469,6 +480,7 @@ def upload(
up_token,
key,
file_path=file_path,
file_name=file_name,
data=data,
data_size=data_size,
modify_time=modify_time,
Expand Down
20 changes: 16 additions & 4 deletions qiniu/services/storage/uploaders/resume_uploader_v2.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import math
from collections import namedtuple
from concurrent import futures
from io import BytesIO
Expand Down Expand Up @@ -65,7 +66,7 @@ def _recover_from_record(
if (
not record_upload_id or
record_modify_time != context.modify_time or
record_expired_at > time()
record_expired_at < time()
):
return context

Expand All @@ -80,6 +81,10 @@ def _recover_from_record(
etag=p['etag']
)
for p in record_etags
if (
p.get('partNumber', None) and
p.get('etag', None)
)
],
resumed=True
)
Expand All @@ -105,7 +110,7 @@ def _set_to_record(self, file_name, key, context):
'etags': [
{
'etag': part.etag,
'part_no': part.part_no
'partNumber': part.part_no
}
for part in context.parts
]
Expand Down Expand Up @@ -170,6 +175,7 @@ def initial_parts(
data_size=None,
modify_time=None,
part_size=None,
file_name=None,
**kwargs
):
"""
Expand All @@ -183,6 +189,7 @@ def initial_parts(
data_size: int
modify_time: int
part_size: int
file_name: str
kwargs

Returns
Expand Down Expand Up @@ -222,7 +229,8 @@ def initial_parts(
)

# try to recover from record
file_name = path.basename(file_path) if file_path else None
if not file_name and file_path:
file_name = path.basename(file_path)
context = self._recover_from_record(
file_name,
key,
Expand Down Expand Up @@ -307,7 +315,10 @@ def upload_parts(

# initial upload state
part, resp = None, None
uploaded_size = 0
uploaded_size = context.part_size * len(context.parts)
if math.ceil(data_size / context.part_size) in [p.part_no for p in context.parts]:
# if last part uploaded, should correct the uploaded size
uploaded_size += (data_size % context.part_size) - context.part_size
lock = Lock()

if not self.concurrent_executor:
Expand Down Expand Up @@ -500,6 +511,7 @@ def upload(
up_token,
key,
file_path=file_path,
file_name=file_name,
data=data,
data_size=data_size,
modify_time=modify_time,
Expand Down
Loading
Loading