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
15 changes: 13 additions & 2 deletions cterasdk/asynchronous/core/files/browser.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from .. import query
from ....cio.core.commands import Open, Upload, Download, EnsureDirectory, \
UnShare, CreateDirectory, GetMetadata, GetProperties, ListVersions, RecursiveIterator, \
UnShare, CreateDirectory, GetMetadata, GetProperties, ListVersions, RecursiveIterator, SearchIterator, \
Delete, Recover, Rename, GetShareMetadata, Link, Copy, Move, ResourceIterator, GetPermalink, GetExternalShareInfo
from ....cio.core.types import InvitationPath
from ....lib.storage import commonfs
Expand Down Expand Up @@ -58,7 +58,7 @@ async def listdir(self, path=None, include_deleted=False):
:raises cterasdk.exceptions.io.core.ListDirectoryError: Raised on error fetching directory contents.
"""
async with EnsureDirectory(io.listdir, self._core, path):
async for o in ResourceIterator(query.iterator, self._core, path, None, include_deleted, None, None).a_execute():
async for o in ResourceIterator(query.iterator, self._core, path, None, include_deleted, None, None, None).a_execute():
yield o

async def properties(self, path):
Expand Down Expand Up @@ -151,6 +151,17 @@ async def permalink(self, path):
"""
return await GetPermalink(io.listdir, self._core, path).a_execute()

async def search(self, path, filters):
"""
Search for files and folders

:param str path: Path
:param list[cterasdk.core.types.SearchFilter], optional filters: Search filters
"""
async with EnsureDirectory(io.listdir, self._core, path):
async for o in SearchIterator(query.iterator, self._core, path, filters).a_execute():
yield o


class CloudDrive(FileBrowser):
"""Async CloudDrive API with upload and sharing functionality."""
Expand Down
18 changes: 14 additions & 4 deletions cterasdk/cio/core/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,12 +437,13 @@ async def _a_execute(self):
class ListDirectory(PortalCommand):
"""List"""

def __init__(self, function, receiver, path, depth, include_deleted, search_criteria, limit):
def __init__(self, function, receiver, path, depth, include_deleted, search_criteria, search_filters, limit):
super().__init__(function, receiver)
self.path = automatic_resolution(path, receiver.context)
self.depth = depth
self.include_deleted = include_deleted
self.search_criteria = search_criteria
self.search_filters = search_filters
self.limit = limit

def get_parameter(self):
Expand All @@ -452,6 +453,8 @@ def get_parameter(self):
builder.include_deleted()
if self.search_criteria:
builder.searchCriteria(self.search_criteria)
if self.search_filters:
builder.searchFilters(self.search_filters)
if self.limit:
builder.limit(self.limit)
return builder.build()
Expand Down Expand Up @@ -499,10 +502,16 @@ def _fetch_resources_error(self, e):
raise error from e


class SearchIterator(ResourceIterator):

def __init__(self, function, receiver, path, search_filters):
super().__init__(function, receiver, path, 'Infinity', False, None, search_filters, None)


class GetMetadata(ListDirectory):

def __init__(self, function, receiver, path, suppress_error=False):
super().__init__(function, receiver, path, 0, False, None, None)
super().__init__(function, receiver, path, 0, False, None, None, None)
self.suppress_error = suppress_error

def _before_command(self):
Expand Down Expand Up @@ -570,15 +579,16 @@ def _generator(self):
def generate(self):
for path in self._generator():
try:
for o in ResourceIterator(self._function, self._receiver, path, None, self.include_deleted, None, None).execute():
for o in ResourceIterator(self._function, self._receiver, path, None, self.include_deleted, None, None, None).execute():
yield self._process_object(o)
except (exceptions.io.core.ListDirectoryError, exceptions.io.core.PrivilegeError) as e:
RecursiveIterator._suppress_error(e)

async def a_generate(self):
for path in self._generator():
try:
async for o in ResourceIterator(self._function, self._receiver, path, None, self.include_deleted, None, None).a_execute():
async for o in ResourceIterator(self._function, self._receiver,
path, None, self.include_deleted, None, None, None).a_execute():
yield self._process_object(o)
except (exceptions.io.core.ListDirectoryError, exceptions.io.core.PrivilegeError) as e:
RecursiveIterator._suppress_error(e)
Expand Down
4 changes: 4 additions & 0 deletions cterasdk/cio/core/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,10 @@ def searchCriteria(self, criteria):
self.param.searchCriteria = criteria # pylint: disable=attribute-defined-outside-init
return self

def searchFilters(self, filters):
self.param.searchFilters = filters # pylint: disable=attribute-defined-outside-init
return self

def include_deleted(self):
self.param.includeDeleted = True # pylint: disable=attribute-defined-outside-init
return self
Expand Down
17 changes: 14 additions & 3 deletions cterasdk/core/files/browser.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from .. import query
from ...cio.core.commands import Open, Upload, Download, EnsureDirectory, \
UnShare, CreateDirectory, GetMetadata, GetProperties, ListVersions, RecursiveIterator, \
UnShare, CreateDirectory, GetMetadata, GetProperties, ListVersions, RecursiveIterator, SearchIterator, \
Delete, Recover, Rename, GetShareMetadata, Link, Copy, Move, ResourceIterator, GetPermalink, GetExternalShareInfo
from ...cio.core.types import InvitationPath
from ...lib.storage import commonfs
Expand Down Expand Up @@ -45,20 +45,21 @@ def download(self, path, objects=None, destination=None):
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):
def listdir(self, path=None, include_deleted=False, filters=None):
"""
List directory contents.

:param str, optional path: Path. Defaults to the Cloud Drive root.
:param bool, optional include_deleted: Include deleted files. Defaults to False.
:param list[cterasdk.core.types.SearchFilter], optional filters: Search filters
:returns: Directory contents.
:rtype: list[cterasdk.cio.core.types.PortalResource]
: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.
:raises cterasdk.exceptions.io.core.ListDirectoryError: Raised on error fetching directory contents.
"""
with EnsureDirectory(io.listdir, self._core, path):
return ResourceIterator(query.iterator, self._core, path, None, include_deleted, None, None).execute()
return ResourceIterator(query.iterator, self._core, path, None, include_deleted, None, filters, None).execute()

def properties(self, path):
"""
Expand Down Expand Up @@ -149,6 +150,16 @@ def permalink(self, path):
"""
return GetPermalink(io.listdir, self._core, path).execute()

def search(self, path, filters):
"""
Search for files and folders

:param str path: Path
:param list[cterasdk.core.types.SearchFilter], optional filters: Search filters
"""
with EnsureDirectory(io.listdir, self._core, path):
return SearchIterator(query.iterator, self._core, path, filters).execute()


class CloudDrive(FileBrowser):
"""CloudDrive extends FileBrowser with upload and share functionality."""
Expand Down
58 changes: 58 additions & 0 deletions cterasdk/core/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -1212,3 +1212,61 @@ def to_server_object(self):
param.collaborator.type = CollaboratorType.from_account(self.account)
param.screened_file_types = [extension.lstrip('.') for extension in self.extensions]
return param


class SearchOperator:
EQUALS = 'eq'
NOT_EQUALS = 'neq'
CONTAINS = 'contains'


class SearchFilter(Object):

def __init__(self, field, operator, value):
super().__init__()
self._classname = 'SearchFilter'
self.field = field
self.operator = operator
self.value = value


class FilenameFilter(SearchFilter):

def __init__(self, operator, value):
super().__init__('name', operator, value)

@staticmethod
def eq(value):
return FilenameFilter(SearchOperator.EQUALS, value)

@staticmethod
def ne(value):
return FilenameFilter(SearchOperator.NOT_EQUALS, value)

@staticmethod
def contains(value):
return FilenameFilter(SearchOperator.CONTAINS, value)


class TypeFilter(SearchFilter):

def __init__(self, operator, value):
super().__init__('extension', operator, value)

@staticmethod
def eq(value):
return TypeFilter(SearchOperator.EQUALS, value)

@staticmethod
def ne(value):
return TypeFilter(SearchOperator.NOT_EQUALS, value)


class ContentFilter(SearchFilter):

def __init__(self, operator, value):
super().__init__('content', operator, value)

@staticmethod
def contains(value):
return ContentFilter(SearchOperator.CONTAINS, value)
21 changes: 21 additions & 0 deletions docs/source/UserGuides/Portal/Files.rst
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ Retrieve a Permalink
permalink = files.permalink('My Files/Keystone Project.docx')
print(f'Permalink: {permalink}')


Create a Public Link
--------------------

Expand All @@ -187,6 +188,23 @@ Create a Public Link
public_url_rw = files.public_link('My Files', access='RW', expire_in=30)
print(f'Public read-write link: {public_url_rw}')


Search
------

.. automethod:: cterasdk.core.files.browser.FileBrowser.search
:noindex:

.. code-block:: python

filters = [
core_types.ContentFilter.contains('The quick brown fox jumped over the lazy dog'),
]

for i in files.public_link('My Files', filters):
print(i.path)


File Handles
------------

Expand Down Expand Up @@ -521,6 +539,9 @@ Asynchronous API
.. automethod:: cterasdk.asynchronous.core.files.browser.FileBrowser.permalink
:noindex:

.. automethod:: cterasdk.asynchronous.core.files.browser.FileBrowser.search
:noindex:

.. automethod:: cterasdk.asynchronous.core.files.browser.CloudDrive.upload
:noindex:

Expand Down
Loading