Skip to content

Commit

Permalink
Merge pull request #536 from leancloud/file-scan-test
Browse files Browse the repository at this point in the history
More fixes on files.
  • Loading branch information
weakish authored Dec 14, 2021
2 parents a05b6e4 + 4c30efd commit 056e079
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 20 deletions.
20 changes: 20 additions & 0 deletions leancloud/file_.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ def __init__(self, name="", data=None, mime_type=None):
self._name = name
self.key = None
self.id = None
self.created_at = None
self.updated_at = None
self._url = None
self._successful_url = None
self._acl = None
Expand Down Expand Up @@ -226,9 +228,18 @@ def _save_external(self):
}
response = client.post("/files".format(self._name), data)
content = response.json()

self.id = content["objectId"]

self._successful_url = self._url

_created_at = utils.decode_date_string(content.get("createdAt"))
_updated_at = utils.decode_updated_at(content.get("updatedAt"), _created_at)
if _created_at is not None:
self.created_at = _created_at
if _updated_at is not None:
self.updated_at = _updated_at

def _save_to_qcloud(self, token, upload_url):
headers = {
"Authorization": token,
Expand Down Expand Up @@ -289,10 +300,19 @@ def _update_data(self, server_data):
if "url" in server_data:
self._url = server_data.get("url")
self._successful_url = self._url
if "key" in server_data:
self.key = server_data.get("key")
if "mime_type" in server_data:
self._mime_type = server_data["mime_type"]
if "metaData" in server_data:
self._metadata = server_data.get("metaData")

_created_at = utils.decode_date_string(server_data.get("createdAt"))
_updated_at = utils.decode_updated_at(server_data.get("updatedAt"), _created_at)
if _created_at is not None:
self.created_at = _created_at
if _updated_at is not None:
self.updated_at = _updated_at

def _get_file_token(self):
data = {
Expand Down
48 changes: 29 additions & 19 deletions leancloud/object_.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,25 +334,18 @@ def _to_pointer(self):
}

def _merge_metadata(self, server_data):
for key in ("objectId", "createdAt", "updatedAt"):
if server_data.get(key) is None:
continue
if key == "objectId":
self.id = server_data[key]
else:
if isinstance(server_data[key], six.string_types):
dt = utils.decode(key, {"__type": "Date", "iso": server_data[key]})
elif server_data[key]["__type"] == "Date":
dt = utils.decode(key, server_data[key])
else:
raise TypeError("Invalid date type")
server_data[key] = dt
if key == "createdAt":
self.created_at = dt
elif key == "updatedAt":
self.updated_at = dt
else:
raise TypeError
object_id = server_data.get("objectId")
_created_at = utils.decode_date_string(server_data.get("createdAt"))
_updated_at = utils.decode_updated_at(server_data.get("updatedAt"), _created_at)

if object_id is not None:
self.id = object_id
if _created_at is not None:
self.created_at = _created_at
if _updated_at is not None:
self.updated_at = _updated_at



def validate(self, attrs):
if "ACL" in attrs and not isinstance(attrs["ACL"], leancloud.ACL):
Expand All @@ -370,6 +363,23 @@ def get(self, attr, default=None, deafult=None):
# for backward compatibility
if (deafult is not None) and (default is None):
default = deafult

# createdAt is stored as string in the cloud but used as datetime object on the client side.
# We need to make sure that `.created_at` and `.get("createdAt")` return the same value.
# Otherwise users will get confused.
if attr == "createdAt":
if self.created_at is None:
return None
else:
return self.created_at

# Similar to createdAt.
if attr == "updatedAt":
if self.updated_at is None:
return None
else:
return self.updated_at

return self._attributes.get(attr, default)

def relation(self, attr):
Expand Down
33 changes: 32 additions & 1 deletion leancloud/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,14 +137,45 @@ def decode(key, value):
if _type == "File":
f = leancloud.File(value["name"])
meta_data = value.get("metaData")
if meta_data:
file_key = value.get("key")
if file_key is not None:
f.key = file_key
if meta_data is not None:
f._metadata = meta_data
f._url = value["url"]
f._successful_url = value["url"]
f.id = value["objectId"]
f.created_at = decode_date_string(value.get("createdAt"))
f.updated_at = decode_date_string(value.get("updatedAt"))
return f


def decode_date_string(date_or_string):
if date_or_string is None:
return None
elif isinstance(date_or_string, six.string_types):
return decode_date_string({"__type": "Date", "iso": date_or_string})
elif date_or_string["__type"] == "Date":
return arrow.get(iso8601.parse_date(date_or_string["iso"])).to("local").datetime
else:
raise TypeError("Invalid date type")


def decode_updated_at(updated_at_date_string, created_at_datetime):
updated_at = decode_date_string(updated_at_date_string)
if updated_at is None:
if created_at_datetime is None:
return None
else:
# When a new object is created, updatedAt will be set as the same value as createdAt on the cloud.
# However, the cloud will only return objectId and createdAt in REST API response, without updatedAt.
# Thus we need to set updatedAt as the same value as createdAt, consistent with the value on the cloud.
# This behaviour is consistent with other SDKs such as JavaScript and Go.
return created_at_datetime
else:
return updated_at


def traverse_object(obj, callback, seen=None):
seen = seen or set()

Expand Down
22 changes: 22 additions & 0 deletions tests/test_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ def test_save(): # type: () -> None
assert f.name == "Blah.txt"
assert f.mime_type == "text/plain"
assert not f.url.endswith(".")
assert f.created_at == f.updated_at


@with_setup(setup_func)
Expand All @@ -118,6 +119,7 @@ def test_save_with_specified_key(): # type: () -> None
f.save()

assert f.id
assert f.created_at == f.updated_at
assert f.name == "Blah.txt"
assert f.mime_type == "text/plain"
path = urlparse(f.url).path
Expand Down Expand Up @@ -146,12 +148,31 @@ def test_query(): # type: () -> None
files = leancloud.Query("File").find()
for f in files:
assert isinstance(f, File)
assert f.id
assert f.url
assert f.name
assert f.metadata
assert f.created_at == f.updated_at
if f.metadata.get("__source") == 'external':
assert f.url
else:
assert f.key

assert isinstance(leancloud.File.query.first(), File)

@with_setup(setup_func)
def test_scan(): # type: () -> None
files = leancloud.Query("File").scan()
for f in files:
assert isinstance(f, File)
assert f.created_at == f.updated_at
assert f.name
assert f.metadata
if f.metadata.get("__source") == 'external':
assert f.url
else:
assert f.key


@with_setup(setup_func)
def test_save_external(): # type: () -> None
Expand All @@ -160,6 +181,7 @@ def test_save_external(): # type: () -> None
f = File.create_with_url(file_name, file_url)
f.save()
assert f.id
assert f.created_at == f.updated_at
file_on_cloud = File.create_without_data(f.id)
file_on_cloud.fetch()
assert file_on_cloud.name == file_name
Expand Down
1 change: 1 addition & 0 deletions tests/test_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ def test_fetch_when_save(): # type: () -> None
foo = Foo()
foo.set("counter", 1)
foo.save()
assert foo.created_at == foo.updated_at
assert foo.get("counter") == 1

foo_from_other_thread = leancloud.Query(Foo).get(foo.id)
Expand Down

0 comments on commit 056e079

Please sign in to comment.