Skip to content
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
71 changes: 33 additions & 38 deletions .pubnub.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: python
version: 10.3.0
version: 10.4.0
schema: 1
scm: github.com/pubnub/python
sdks:
Expand All @@ -18,16 +18,17 @@ sdks:
distributions:
- distribution-type: library
distribution-repository: package
package-name: pubnub-10.3.0
package-name: pubnub-10.4.0
location: https://pypi.org/project/pubnub/
supported-platforms:
supported-operating-systems:
Linux:
runtime-version:
- Python 3.7
- Python 3.8
- Python 3.9
- Python 3.10
- Python 3.11
- Python 3.12
- Python 3.13
minimum-os-version:
- Ubuntu 12.04
maximum-os-version:
Expand All @@ -37,10 +38,11 @@ sdks:
- x86-64
macOS:
runtime-version:
- Python 3.7
- Python 3.8
- Python 3.9
- Python 3.10
- Python 3.11
- Python 3.12
- Python 3.13
minimum-os-version:
- macOS 10.12
maximum-os-version:
Expand All @@ -49,10 +51,11 @@ sdks:
- x86-64
Windows:
runtime-version:
- Python 3.7
- Python 3.8
- Python 3.9
- Python 3.10
- Python 3.11
- Python 3.12
- Python 3.13
minimum-os-version:
- Windows Vista Ultimate
maximum-os-version:
Expand Down Expand Up @@ -91,16 +94,17 @@ sdks:
-
distribution-type: library
distribution-repository: git release
package-name: pubnub-10.3.0
location: https://github.com/pubnub/python/releases/download/10.3.0/pubnub-10.3.0.tar.gz
package-name: pubnub-10.4.0
location: https://github.com/pubnub/python/releases/download/10.4.0/pubnub-10.4.0.tar.gz
supported-platforms:
supported-operating-systems:
Linux:
runtime-version:
- Python 3.7
- Python 3.8
- Python 3.9
- Python 3.10
- Python 3.11
- Python 3.12
- Python 3.13
minimum-os-version:
- Ubuntu 12.04
maximum-os-version:
Expand All @@ -110,10 +114,11 @@ sdks:
- x86-64
macOS:
runtime-version:
- Python 3.7
- Python 3.8
- Python 3.9
- Python 3.10
- Python 3.11
- Python 3.12
- Python 3.13
minimum-os-version:
- macOS 10.12
maximum-os-version:
Expand All @@ -122,10 +127,11 @@ sdks:
- x86-64
Windows:
runtime-version:
- Python 3.7
- Python 3.8
- Python 3.9
- Python 3.10
- Python 3.11
- Python 3.12
- Python 3.13
minimum-os-version:
- Windows Vista Ultimate
maximum-os-version:
Expand Down Expand Up @@ -163,6 +169,11 @@ sdks:
license-url: https://github.com/encode/httpx/blob/master/LICENSE.md
is-required: Required
changelog:
- date: 2025-05-07
version: 10.4.0
changes:
- type: feature
text: "Added pagination to List Files."
- date: 2025-04-10
version: 10.3.0
changes:
Expand Down Expand Up @@ -772,19 +783,6 @@ supported-platforms:
- python 3.5.2
- python 3.6.0
- pypy
-
version: PubNub Python Tornado SDK
platforms:
- FreeBSD 8-STABLE or later, amd64, 386
- Linux 2.6 or later, amd64, 386.
- Mac OS X 10.8 or later, amd64
- Windows 7 or later, amd64, 386
editors:
- python 2.7.13
- python 3.4.5
- python 3.5.2
- python 3.6.0
- pypy
-
version: PubNub Python Asyncio SDK
platforms:
Expand All @@ -793,12 +791,9 @@ supported-platforms:
- Mac OS X 10.8 or later, amd64
- Windows 7 or later, amd64, 386
editors:
- python 3.4.5
- python 3.5.2
- python 3.6.0
-
version: PubNub Python Twisted SDK
platforms:
- Linux 2.6 or later, amd64, 386.
editors:
- python 2.7.13
- python 3.9.21
- python 3.10.16
- python 3.11.11
- python 3.12.9
- python 3.13.2

6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 10.4.0
May 07 2025

#### Added
- Added pagination to List Files.

## 10.3.0
April 10 2025

Expand Down
13 changes: 7 additions & 6 deletions pubnub/endpoints/entities/endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,13 @@ def spaces(self, spaces):
class ListEndpoint:
__metaclass__ = ABCMeta

def __init__(self):
self._limit = None
self._filter = None
self._include_total_count = None
self._sort_keys = None
self._page = None
def __init__(self, limit: int = None, filter: str = None, include_total_count: bool = None,
sort_keys: list = None, page: str = None):
self._limit = limit
self._filter = filter
self._include_total_count = include_total_count
self._sort_keys = sort_keys
self._page = page

def limit(self, limit):
self._limit = int(limit)
Expand Down
23 changes: 20 additions & 3 deletions pubnub/endpoints/file_operations/list_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,43 @@ class PNGetFilesResultEnvelope(Envelope):
class ListFiles(FileOperationEndpoint):
LIST_FILES_URL = "/v1/files/%s/channels/%s/files"
_channel: str
_limit: int
_next: str

def __init__(self, pubnub, channel: str = None):
def __init__(self, pubnub, channel: str = None, *, limit: int = None, next: str = None):
FileOperationEndpoint.__init__(self, pubnub)
self._channel = channel
self._limit = limit
self._next = next

def build_path(self):
return ListFiles.LIST_FILES_URL % (
self.pubnub.config.subscribe_key,
utils.url_encode(self._channel)
)

def channel(self, channel) -> 'ListFiles':
def channel(self, channel: str) -> 'ListFiles':
self._channel = channel
return self

def limit(self, limit: int) -> 'ListFiles':
self._limit = limit
return self

def next(self, next: str) -> 'ListFiles':
self._next = next
return self

def http_method(self):
return HttpMethod.GET

def custom_params(self):
return {}
params = {}
if self._limit:
params["limit"] = str(self._limit)
if self._next:
params["next"] = str(self._next)
return params

def is_auth_required(self):
return True
Expand Down
1 change: 0 additions & 1 deletion pubnub/models/consumer/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ def __init__(self, result):
self.data = result['data']
self.count = result.get('count', None)
self.next = result.get('next', None)
self.prev = result.get('prev', None)

def __str__(self):
return "Get files success with data: %s" % self.data
Expand Down
6 changes: 3 additions & 3 deletions pubnub/pubnub_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@

class PubNubCore:
"""A base class for PubNub Python API implementations"""
SDK_VERSION = "10.3.0"
SDK_VERSION = "10.4.0"
SDK_NAME = "PubNub-Python"

TIMESTAMP_DIVIDER = 1000
Expand Down Expand Up @@ -466,8 +466,8 @@ def download_file(self):
else:
raise NotImplementedError

def list_files(self, channel: str = None) -> ListFiles:
return ListFiles(self, channel=channel)
def list_files(self, channel: str = None, *, limit: int = None, next: str = None) -> ListFiles:
return ListFiles(self, channel=channel, limit=limit, next=next)

def get_file_url(self, channel: str = None, file_name: str = None, file_id: str = None) -> GetFileDownloadUrl:
return GetFileDownloadUrl(self, channel=channel, file_name=file_name, file_id=file_id)
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

setup(
name='pubnub',
version='10.3.0',
version='10.4.0',
description='PubNub Real-time push service in the cloud',
author='PubNub',
author_email='support@pubnub.com',
Expand Down
79 changes: 77 additions & 2 deletions tests/integrational/asyncio/test_file_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,87 @@ async def test_delete_file(file_for_upload):
filter_query_parameters=['uuid', 'l_file', 'pnsdk']
)
@pytest.mark.asyncio(loop_scope="module")
async def test_list_files():
async def test_list_files(file_for_upload, file_upload_test_data):
pubnub = PubNubAsyncio(pnconf_env_copy())
pubnub.config.uuid = "files_asyncio_uuid"

# Clear existing files first to ensure a clean state
envelope = await pubnub.list_files().channel(CHANNEL).future()
files = envelope.result.data
for i in range(len(files)):
file = files[i]
await pubnub.delete_file().channel(CHANNEL).file_id(file["id"]).file_name(file["name"]).future()

envelope = await send_file(pubnub, file_for_upload)

envelope = await pubnub.list_files().channel(CHANNEL).future()

assert isinstance(envelope.result, PNGetFilesResult)
assert envelope.result.count == 1
assert file_upload_test_data["UPLOADED_FILENAME"] == envelope.result.data[0]["name"]
await pubnub.stop()


@pn_vcr.use_cassette(
"tests/integrational/fixtures/asyncio/file_upload/list_files_with_limit.json", serializer="pn_json",
filter_query_parameters=['uuid', 'l_file', 'pnsdk']
)
@pytest.mark.asyncio(loop_scope="module")
async def test_list_files_with_limit(file_for_upload, file_upload_test_data):
pubnub = PubNubAsyncio(pnconf_env_copy())
pubnub.config.uuid = "files_asyncio_uuid"
await send_file(pubnub, file_for_upload)
await send_file(pubnub, file_for_upload)
envelope = await pubnub.list_files().channel(CHANNEL).limit(2).future()
assert isinstance(envelope.result, PNGetFilesResult)
assert envelope.result.count == 2
assert file_upload_test_data["UPLOADED_FILENAME"] == envelope.result.data[0]["name"]
await pubnub.stop()


@pn_vcr.use_cassette(
"tests/integrational/fixtures/asyncio/file_upload/list_files_with_page.json", serializer="pn_json",
filter_query_parameters=['uuid', 'l_file', 'pnsdk']
)
@pytest.mark.asyncio(loop_scope="module")
async def test_list_files_with_page(file_for_upload, file_upload_test_data):
pubnub = PubNubAsyncio(pnconf_env_copy())
pubnub.config.uuid = "files_asyncio_uuid"
await send_file(pubnub, file_for_upload)
await send_file(pubnub, file_for_upload)
envelope = await pubnub.list_files().channel(CHANNEL).limit(2).future()
assert isinstance(envelope.result, PNGetFilesResult)
assert envelope.result.count == 2
assert envelope.result.next is not None
next_page = envelope.result.next
file_ids = [envelope.result.data[0]['id'], envelope.result.data[1]['id']]
envelope = await pubnub.list_files().channel(CHANNEL).limit(2).next(next_page).future()
assert isinstance(envelope.result, PNGetFilesResult)
assert envelope.result.count == 2
assert envelope.result.next is not None
assert envelope.result.data[0]['id'] not in file_ids
assert envelope.result.data[1]['id'] not in file_ids
assert file_upload_test_data["UPLOADED_FILENAME"] == envelope.result.data[0]["name"]
await pubnub.stop()


# @pn_vcr.use_cassette( # Needs new recording for asyncio
# "tests/integrational/fixtures/asyncio/file_upload/delete_all_files.json", serializer="pn_json",
# filter_query_parameters=['uuid', 'l_file', 'pnsdk']
# )
@pytest.mark.asyncio(loop_scope="module")
async def test_delete_all_files():
pubnub = PubNubAsyncio(pnconf_env_copy())
pubnub.config.uuid = "files_asyncio_uuid"
envelope = await pubnub.list_files().channel(CHANNEL).future()
files = envelope.result.data
for i in range(len(files)):
file = files[i]
await pubnub.delete_file().channel(CHANNEL).file_id(file["id"]).file_name(file["name"]).future()
envelope = await pubnub.list_files().channel(CHANNEL).future()

assert isinstance(envelope.result, PNGetFilesResult)
assert envelope.result.count == 7
assert envelope.result.count == 0
await pubnub.stop()


Expand Down
Loading
Loading