From 2f011d911d54c1fd8a9d31d8e1ce8f8f368115ad Mon Sep 17 00:00:00 2001 From: Saimon Michelson Date: Sun, 3 May 2026 18:48:18 -0400 Subject: [PATCH 1/7] consolidate handle handle_many and download download_many functions --- cterasdk/asynchronous/core/files/browser.py | 69 +++++-------- cterasdk/cio/core/commands.py | 101 +++++++------------- cterasdk/cli/dav.py | 4 +- cterasdk/core/files/browser.py | 53 +++------- cterasdk/lib/storage/commonfs.py | 2 +- docs/source/UserGuides/Portal/Files.rst | 21 ++-- 6 files changed, 84 insertions(+), 166 deletions(-) diff --git a/cterasdk/asynchronous/core/files/browser.py b/cterasdk/asynchronous/core/files/browser.py index a9751e7b..b7be366d 100644 --- a/cterasdk/asynchronous/core/files/browser.py +++ b/cterasdk/asynchronous/core/files/browser.py @@ -1,6 +1,6 @@ from .. import query -from ....cio.core.commands import Open, OpenMany, Upload, Download, EnsureDirectory, \ - DownloadMany, UnShare, CreateDirectory, GetMetadata, GetProperties, ListVersions, RecursiveIterator, \ +from ....cio.core.commands import Open, Upload, Download, EnsureDirectory, \ + UnShare, CreateDirectory, GetMetadata, GetProperties, ListVersions, RecursiveIterator, \ Delete, Recover, Rename, GetShareMetadata, Link, Copy, Move, ResourceIterator, GetPermalink, GetExternalShareInfo from ....cio.core.types import InvitationPath from ....lib.storage import commonfs @@ -11,60 +11,40 @@ class FileBrowser(BaseCommand): """Async File Browser API.""" - async def handle(self, path): + async def handle(self, path, objects): """ Get a file handle. :param str path: Path to a file. + :param list[str],optional objects: Files and folders to include. :returns: File handle. :rtype: object - :raises cterasdk.exceptions.io.core.OpenError: Raised on error to obtain file handle. + :raises cterasdk.exceptions.io.core.OpenError: Raised on error to obtain a file handle. + :raises cterasdk.exceptions.io.core.GetMetadataError: If the directory was not found. + :raises cterasdk.exceptions.io.core.NotADirectoryException: If the target path is not a directory. """ - return await Open(io.handle, self._core, path).a_execute() + async with GetProperties(io.listdir, self._core, path) as properties: + return await Open(io.handle_many if properties.is_dir else io.handle, self._core, + properties.path, properties, objects).a_execute() - async def handle_many(self, directory, *objects): - """ - Get a ZIP archive file handle. - - :param str directory: Path to a folder. - :param args objects: List of files and folders to include. - :returns: File handle. - :rtype: object - :raises cterasdk.exceptions.io.core.GetMetadataError: If directory not found. - :raises cterasdk.exceptions.io.core.NotADirectoryException: If target path is not a directory. - """ - async with EnsureDirectory(io.listdir, self._core, directory) as (_, resource): - return await OpenMany(io.handle_many, self._core, resource, directory, *objects).a_execute() - - async def download(self, path, destination=None): + async def download(self, path, objects=None, destination=None): """ Download a file. :param str path: Path. - :param str, optional destination: File destination. If directory, original filename preserved. Defaults to default directory. - :returns: Path to local file. + :param list[str],optional objects: List of files and / or directory names to download. + :param str, optional destination: File destination. If a directory is provided, the original filename is preserved. + Defaults to the default download directory. + :returns: Path to the local file. :rtype: str - :raises cterasdk.exceptions.io.core.OpenError: Raised on error to obtain file handle. + :raises cterasdk.exceptions.io.core.OpenError: Raised on error to obtain a file handle. + :raises cterasdk.exceptions.io.core.GetMetadataError: If the directory was not found. + :raises cterasdk.exceptions.io.core.NotADirectoryException: If the target path is not a directory. """ - return await Download(io.handle, self._core, path, destination).a_execute() + async with GetProperties(io.listdir, self._core, path) as properties: + return await Download(io.handle_many if properties.is_dir else io.handle, self._core, + properties.path, properties, objects, destination).a_execute() - async def download_many(self, directory, objects, destination=None): - """ - Download selected files and/or directories as a ZIP archive. - - .. warning:: - Only existing files and directories will be included in the resulting ZIP file. - - :param str directory: Path to a folder. - :param list[str] objects: List of files and / or directory names to download. - :param str destination: Optional path to destination file or directory. Defaults to default download directory. - :returns: Path to local file. - :rtype: str - :raises cterasdk.exceptions.io.core.GetMetadataError: If directory not found. - :raises cterasdk.exceptions.io.core.NotADirectoryException: If target path is not a directory. - """ - async with EnsureDirectory(io.listdir, self._core, directory) as (_, resource): - return await DownloadMany(io.handle_many, self._core, resource, directory, objects, destination).a_execute() async def listdir(self, path=None, include_deleted=False): """ @@ -383,11 +363,8 @@ async def mkdir(self, path): async def makedirs(self, path): return await self._file_browser.makedirs(self._invitation.join(path)) - async def download(self, path, destination=None): - return await self._file_browser.download(self._invitation.join(path), destination) - - async def download_many(self, directory, objects, destination=None): - return await self._file_browser.download_many(self._invitation.join(directory), objects, destination) + async def download(self, path, objects=None, destination=None): + return await self._file_browser.download(self._invitation.join(path), objects, destination) async def upload(self, destination, handle, name=None, size=None): return await self._file_browser.upload(self._invitation.join(destination), handle, name, size) diff --git a/cterasdk/cio/core/commands.py b/cterasdk/cio/core/commands.py index bb9d0b02..e26c1a4c 100644 --- a/cterasdk/cio/core/commands.py +++ b/cterasdk/cio/core/commands.py @@ -356,24 +356,42 @@ def obtain_current_accounts(collaborators): class Open(PortalCommand): """Open file""" - def __init__(self, function, receiver, path): + def __init__(self, function, receiver, path, properties, objects): super().__init__(function, receiver) self.path = automatic_resolution(path, receiver.context) + self.properties = properties + self.objects = objects or [] def get_parameter(self): - return self.path.relative_encode + if self.properties.is_dir: + param = Object() + param.paths = [self.path.join(filename).absolute_encode for filename in self.objects] if self.objects else [self.path.absolute] + param.snapshot = None + param.password = None + param.portalName = None + param.showDeleted = False + uid = ( + str(self.properties.volume.id) + if self._receiver.context != Context.Invitations + else f'share/{self._receiver.invite}' + ) + return uid, encode_request_parameter(param) + return self.path.relative_encode, def _before_command(self): raise_or_suppress_access_error(self._receiver, self.path) - logger.info('Getting handle: %s', self.path) + if self.properties.is_dir and self.objects: + logger.info('Getting handle: %s', [self.path.join(o).relative for o in self.objects]) + else: + logger.info('Getting handle: %s', self.path) def _execute(self): with self.trace_execution(): - return self._function(self._receiver, self.get_parameter()) + return self._function(self._receiver, *self.get_parameter()) async def _a_execute(self): with self.trace_execution(): - return await self._function(self._receiver, self.get_parameter()) + return await self._function(self._receiver, *self.get_parameter()) def _handle_exception(self, e): path = self.path.relative @@ -385,86 +403,33 @@ def _handle_exception(self, e): class Download(PortalCommand): - def __init__(self, function, receiver, path, destination): + def __init__(self, function, receiver, path, properties, objects, destination): super().__init__(function, receiver) self.path = automatic_resolution(path, receiver.context) - self.destination = destination - - def get_parameter(self): - return commonfs.determine_directory_and_filename(self.path.reference, destination=self.destination) - - def _before_command(self): - logger.info('Downloading: %s', self.path) - - def _execute(self): - directory, name = self.get_parameter() - with self.trace_execution(): - with Open(self._function, self._receiver, self.path) as handle: - return synfs.write(directory, name, handle) - - async def _a_execute(self): - directory, name = self.get_parameter() - with self.trace_execution(): - async with Open(self._function, self._receiver, self.path) as handle: - return await asynfs.write(directory, name, handle) - - -class OpenMany(PortalCommand): - - def __init__(self, function, receiver, resource, directory, *objects): - super().__init__(function, receiver) - self.uid = str(resource.cloudFolderInfo.uid) if receiver.context != Context.Invitations else f'share/{receiver.invite}' - self.directory = automatic_resolution(directory, receiver.context) - self.objects = objects - - def _before_command(self): - raise_or_suppress_access_error(self._receiver, self.directory) - logger.info('Getting handle: %s', [self.directory.join(o).relative for o in self.objects]) - - def get_parameter(self): - param = Object() - param.paths = [self.directory.join(filename).absolute_encode for filename in self.objects] - param.snapshot = None - param.password = None - param.portalName = None - param.showDeleted = False - return encode_request_parameter(param) - - def _execute(self): - with self.trace_execution(): - return self._function(self._receiver, self.uid, self.get_parameter()) - - async def _a_execute(self): - with self.trace_execution(): - return await self._function(self._receiver, self.uid, self.get_parameter()) - - -class DownloadMany(PortalCommand): - - def __init__(self, function, receiver, resource, directory, objects, destination): - super().__init__(function, receiver) - self.resource = resource - self.directory = automatic_resolution(directory, receiver.context) + self.properties = properties self.objects = objects self.destination = destination def get_parameter(self): - return commonfs.determine_directory_and_filename(self.directory.reference, self.objects, destination=self.destination, archive=True) + return commonfs.determine_directory_and_filename(self.path.reference,self.objects, + self.destination, self.properties.is_dir) def _before_command(self): - for o in self.objects: - logger.info('Downloading: %s', self.directory.join(o).relative) + if self.properties.is_dir and self.objects: + logger.info('Downloading: %s', [self.path.join(o).relative for o in self.objects]) + else: + logger.info('Downloading: %s', self.path) def _execute(self): directory, name = self.get_parameter() with self.trace_execution(): - with OpenMany(self._function, self._receiver, self.resource, self.directory, *self.objects) as handle: + with Open(self._function, self._receiver, self.path, self.properties, self.objects) as handle: return synfs.write(directory, name, handle) async def _a_execute(self): directory, name = self.get_parameter() with self.trace_execution(): - async with OpenMany(self._function, self._receiver, self.resource, self.directory, *self.objects) as handle: + async with Open(self._function, self._receiver, self.path, self.properties, self.objects) as handle: return await asynfs.write(directory, name, handle) diff --git a/cterasdk/cli/dav.py b/cterasdk/cli/dav.py index 95e14a4b..71484a82 100644 --- a/cterasdk/cli/dav.py +++ b/cterasdk/cli/dav.py @@ -53,8 +53,8 @@ async def handle_download(args): # pylint: disable=too-many-branches async def download(invitation, resource, objects=None, archive=False, destination=None): if objects is not None or archive: - return await invitation.files.download_many(resource.path.relative, [o.name for o in objects], f'{destination}.zip') - return await invitation.files.download(resource.path.relative, destination.joinpath(resource.path.relative)) + return await invitation.files.download(resource.path.relative, [o.name for o in objects], f'{destination}.zip') + return await invitation.files.download(resource.path.relative, destination=destination.joinpath(resource.path.relative)) async with AsyncInvitation.from_uri(args.endpoint) as invitation: jobs = [] diff --git a/cterasdk/core/files/browser.py b/cterasdk/core/files/browser.py index c02da87e..be5d4ce9 100644 --- a/cterasdk/core/files/browser.py +++ b/cterasdk/core/files/browser.py @@ -1,6 +1,6 @@ from .. import query -from ...cio.core.commands import Open, OpenMany, Upload, Download, EnsureDirectory, \ - DownloadMany, UnShare, CreateDirectory, GetMetadata, GetProperties, ListVersions, RecursiveIterator, \ +from ...cio.core.commands import Open, Upload, Download, EnsureDirectory, \ + UnShare, CreateDirectory, GetMetadata, GetProperties, ListVersions, RecursiveIterator, \ Delete, Recover, Rename, GetShareMetadata, Link, Copy, Move, ResourceIterator, GetPermalink, GetExternalShareInfo from ...cio.core.types import InvitationPath from ...lib.storage import commonfs @@ -11,61 +11,39 @@ class FileBrowser(BaseCommand): """CTERA Portal File Browser API.""" - def handle(self, path): + def handle(self, path, objects=None): """ Get a file handle. :param str path: Path to a file. + :param list[str],optional objects: Files and folders to include. :returns: File handle. :rtype: object :raises cterasdk.exceptions.io.core.OpenError: Raised on error to obtain a file handle. - """ - return Open(io.handle, self._core, path).execute() - - def handle_many(self, directory, *objects): - """ - Get a ZIP archive file handle. - - :param str directory: Path to a folder. - :param args objects: Files and folders to include. - :returns: File handle. - :rtype: object :raises cterasdk.exceptions.io.core.GetMetadataError: If the directory was not found. :raises cterasdk.exceptions.io.core.NotADirectoryException: If the target path is not a directory. """ - with EnsureDirectory(io.listdir, self._core, directory) as (_, resource): - return OpenMany(io.handle_many, self._core, resource, directory, *objects).execute() + with GetProperties(io.listdir, self._core, path) as properties: + return Open(io.handle_many if properties.is_dir else io.handle, self._core, + properties.path, properties, objects).execute() - def download(self, path, destination=None): + def download(self, path, objects=None, destination=None): """ Download a file. :param str path: Path. + :param list[str],optional objects: List of files and / or directory names to download. :param str, optional destination: File destination. If a directory is provided, the original filename is preserved. Defaults to the default download directory. :returns: Path to the local file. :rtype: str :raises cterasdk.exceptions.io.core.OpenError: Raised on error to obtain a file handle. - """ - return Download(io.handle, self._core, path, destination).execute() - - def download_many(self, directory, objects, destination=None): - """ - Download selected files and/or directories as a ZIP archive. - - .. warning:: - Only existing files and directories will be included in the resulting ZIP file. - - :param str directory: Path to a folder. - :param list[str] objects: List of files and / or directory names to download. - :param str destination: Optional path to destination file or directory. Defaults to the default download directory. - :returns: Path to the local file. - :rtype: str :raises cterasdk.exceptions.io.core.GetMetadataError: If the directory was not found. :raises cterasdk.exceptions.io.core.NotADirectoryException: If the target path is not a directory. """ - with EnsureDirectory(io.listdir, self._core, directory) as (_, resource): - return DownloadMany(io.handle_many, self._core, resource, directory, objects, destination).execute() + with GetProperties(io.listdir, self._core, path) as properties: + return Download(io.handle_many if properties.is_dir else io.handle, self._core, + properties.path, properties, objects, destination).execute() def listdir(self, path=None, include_deleted=False): """ @@ -380,11 +358,8 @@ def mkdir(self, path): def makedirs(self, path): return self._file_browser.makedirs(self._invitation.join(path)) - def download(self, path, destination=None): - return self._file_browser.download(self._invitation.join(path), destination) - - def download_many(self, directory, objects, destination=None): - return self._file_browser.download_many(self._invitation.join(directory), objects, destination) + def download(self, path, objects=None, destination=None): + return self._file_browser.download(self._invitation.join(path), objects, destination) def upload(self, destination, handle, name=None, size=None): return self._file_browser.upload(self._invitation.join(destination), handle, name, size) diff --git a/cterasdk/lib/storage/commonfs.py b/cterasdk/lib/storage/commonfs.py index bf5d3dd1..98791210 100644 --- a/cterasdk/lib/storage/commonfs.py +++ b/cterasdk/lib/storage/commonfs.py @@ -96,7 +96,7 @@ def determine_zip_archive_name(directory, objects): :rtype: str """ - if len(objects) > 1: + if not objects or len(objects) > 1: path = Path(directory) else: path = Path(objects[0]) diff --git a/docs/source/UserGuides/Portal/Files.rst b/docs/source/UserGuides/Portal/Files.rst index cf4a7792..5ab62b13 100644 --- a/docs/source/UserGuides/Portal/Files.rst +++ b/docs/source/UserGuides/Portal/Files.rst @@ -195,13 +195,14 @@ File Handles .. code-block:: python + """Retrieve a handle for a file""" handle = files.handle('My Files/Keystone Project.docx') -.. automethod:: cterasdk.core.files.browser.FileBrowser.handle_many + """Retrieve a handle for a folder""" + handle = files.handle('My Files/Project X') -.. code-block:: python - - handle = files.handle_many('My Files', 'Keystone Project.docx', 'Images', 'Notes.txt') + """Retrieve a handle for individual files within a folder""" + handle = files.handle('My Files', ['Keystone Project.docx', 'Images', 'Notes.txt']) Downloading Files ----------------- @@ -211,14 +212,14 @@ Downloading Files .. code-block:: python - local_path = files.download('My Files/Keystone Project.docx') + """Download a file""" + path = files.download('My Files/Keystone Project.docx') -.. automethod:: cterasdk.core.files.browser.FileBrowser.download_many - :noindex: - -.. code-block:: python + """Download a folder""" + path = files.download('My Files/Project X') - zip_path = files.download_many('My Files', ['Keystone Project.docx', 'Images'], destination='/tmp/MyFiles.zip') + """Download individual files within a folder""" + zip_archive = files.download('My Files', ['Keystone Project.docx', 'Images'], destination='/tmp/MyFiles.zip') Create Directories ------------------ From 95493a3bd2c9e5fd41ae9fe558d7dc2749dc4e5a Mon Sep 17 00:00:00 2001 From: Saimon Michelson Date: Mon, 4 May 2026 11:31:51 -0400 Subject: [PATCH 2/7] update for flake8 and pylint --- cterasdk/asynchronous/core/files/browser.py | 1 - cterasdk/cio/core/commands.py | 4 ++-- cterasdk/core/files/browser.py | 3 ++- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cterasdk/asynchronous/core/files/browser.py b/cterasdk/asynchronous/core/files/browser.py index b7be366d..3b8a7ff4 100644 --- a/cterasdk/asynchronous/core/files/browser.py +++ b/cterasdk/asynchronous/core/files/browser.py @@ -45,7 +45,6 @@ async def download(self, path, objects=None, destination=None): return await Download(io.handle_many if properties.is_dir else io.handle, self._core, properties.path, properties, objects, destination).a_execute() - async def listdir(self, path=None, include_deleted=False): """ List directory contents. diff --git a/cterasdk/cio/core/commands.py b/cterasdk/cio/core/commands.py index e26c1a4c..d0f1eb0b 100644 --- a/cterasdk/cio/core/commands.py +++ b/cterasdk/cio/core/commands.py @@ -376,7 +376,7 @@ def get_parameter(self): else f'share/{self._receiver.invite}' ) return uid, encode_request_parameter(param) - return self.path.relative_encode, + return self.path.relative_encode, # pylint: disable=trailing-comma-tuple def _before_command(self): raise_or_suppress_access_error(self._receiver, self.path) @@ -411,7 +411,7 @@ def __init__(self, function, receiver, path, properties, objects, destination): self.destination = destination def get_parameter(self): - return commonfs.determine_directory_and_filename(self.path.reference,self.objects, + return commonfs.determine_directory_and_filename(self.path.reference, self.objects, self.destination, self.properties.is_dir) def _before_command(self): diff --git a/cterasdk/core/files/browser.py b/cterasdk/core/files/browser.py index be5d4ce9..f84bae98 100644 --- a/cterasdk/core/files/browser.py +++ b/cterasdk/core/files/browser.py @@ -330,7 +330,8 @@ def device_config(self, device, destination=None): :raises cterasdk.exceptions.io.core.OpenError: Raised on error obtaining file handle. """ destination = destination if destination is not None else f'{commonfs.downloads()}/{device}.xml' - return Download(io.handle, self._core, f'backups/{device}/Device Configuration/db.xml', destination).execute() + return Download(io.handle, self._core, + f'backups/{device}/Device Configuration/db.xml', destination=destination).execute() class InvitationBrowser: From 3911bd98d7b18d94e3c897e988754e6a83b9caef Mon Sep 17 00:00:00 2001 From: Saimon Michelson Date: Mon, 4 May 2026 11:49:17 -0400 Subject: [PATCH 3/7] support downloads of device config --- cterasdk/cio/core/commands.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/cterasdk/cio/core/commands.py b/cterasdk/cio/core/commands.py index d0f1eb0b..ff6f471a 100644 --- a/cterasdk/cio/core/commands.py +++ b/cterasdk/cio/core/commands.py @@ -363,7 +363,7 @@ def __init__(self, function, receiver, path, properties, objects): self.objects = objects or [] def get_parameter(self): - if self.properties.is_dir: + if self.properties and self.properties.is_dir: param = Object() param.paths = [self.path.join(filename).absolute_encode for filename in self.objects] if self.objects else [self.path.absolute] param.snapshot = None @@ -380,7 +380,7 @@ def get_parameter(self): def _before_command(self): raise_or_suppress_access_error(self._receiver, self.path) - if self.properties.is_dir and self.objects: + if self.properties and self.properties.is_dir and self.objects: logger.info('Getting handle: %s', [self.path.join(o).relative for o in self.objects]) else: logger.info('Getting handle: %s', self.path) @@ -403,7 +403,7 @@ def _handle_exception(self, e): class Download(PortalCommand): - def __init__(self, function, receiver, path, properties, objects, destination): + def __init__(self, function, receiver, path, properties=None, objects=None, destination=None): super().__init__(function, receiver) self.path = automatic_resolution(path, receiver.context) self.properties = properties @@ -411,11 +411,12 @@ def __init__(self, function, receiver, path, properties, objects, destination): self.destination = destination def get_parameter(self): + archive = self.properties.is_dir if self.properties else False return commonfs.determine_directory_and_filename(self.path.reference, self.objects, - self.destination, self.properties.is_dir) + self.destination, archive) def _before_command(self): - if self.properties.is_dir and self.objects: + if self.properties and self.properties.is_dir and self.objects: logger.info('Downloading: %s', [self.path.join(o).relative for o in self.objects]) else: logger.info('Downloading: %s', self.path) From 1dc2b8097dbf5b0d835ffeb6e1a53837a07c50a0 Mon Sep 17 00:00:00 2001 From: Saimon Michelson Date: Mon, 4 May 2026 12:06:25 -0400 Subject: [PATCH 4/7] update to pass tox --- tests/ut/core/user/test_special_characters.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/ut/core/user/test_special_characters.py b/tests/ut/core/user/test_special_characters.py index 69db0f96..26a5beed 100644 --- a/tests/ut/core/user/test_special_characters.py +++ b/tests/ut/core/user/test_special_characters.py @@ -35,6 +35,7 @@ def setUp(self): self._special_dir = 'My Files/100% Complete' self._special_filename = 'file_100%_done.txt' self._special_path = f'{self._special_dir}/{self._special_filename}' + self._mock_properties_response = self.patch_call('cterasdk.cio.core.commands.GetProperties._handle_response') def _expected_encoded_absolute(self, path): return f'{self._base}/{quote(path)}' @@ -44,6 +45,7 @@ def _expected_encoded_absolute(self, path): def test_handle_encodes_special_characters(self): for filename in self.SPECIAL_FILENAMES: path = f'My Files/{filename}' + self._mock_properties_response.return_value = munch.Munch({'is_dir': False, 'path': path}) self._init_services() mock_download = mock.MagicMock() self._services.io._webdav.download = mock_download # pylint: disable=protected-access @@ -57,6 +59,7 @@ def test_handle_encodes_special_characters(self): def test_handle_percent_in_directory(self): for directory in self.SPECIAL_DIRECTORIES: path = f'{directory}/document.txt' + self._mock_properties_response.return_value = munch.Munch({'is_dir': False, 'path': path}) self._init_services() mock_download = mock.MagicMock() self._services.io._webdav.download = mock_download # pylint: disable=protected-access From 50ea13d0509d2c21240de539aa1502dcec4536f2 Mon Sep 17 00:00:00 2001 From: Saimon Michelson Date: Tue, 5 May 2026 12:20:08 -0400 Subject: [PATCH 5/7] update ci.yml --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9e8178a8..24ab68c9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: - name: Coveralls env: COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} - run: coveralls + run: coveralls --service=github-actions deploy: needs: build if: github.event_name == 'release' From 7cde3ba6c306927c9f847271f975bdacfb2b7608 Mon Sep 17 00:00:00 2001 From: Saimon Michelson Date: Tue, 5 May 2026 12:37:44 -0400 Subject: [PATCH 6/7] try uisng github token instead of coveralls repo token --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 24ab68c9..bfbf9ac8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,8 +31,8 @@ jobs: run: tox - name: Coveralls env: - COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} - run: coveralls --service=github-actions + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: coveralls deploy: needs: build if: github.event_name == 'release' From 64e018cf149d810a648fb556d9602172844bbf85 Mon Sep 17 00:00:00 2001 From: Saimon Michelson Date: Tue, 5 May 2026 12:48:18 -0400 Subject: [PATCH 7/7] back to previous config --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bfbf9ac8..9e8178a8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: run: tox - name: Coveralls env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} run: coveralls deploy: needs: build