diff --git a/squarecloud/client.py b/squarecloud/client.py index 4390905..47ac953 100644 --- a/squarecloud/client.py +++ b/squarecloud/client.py @@ -386,7 +386,8 @@ async def upload_app(self, file: File, if not isinstance(file, File): raise InvalidFile( f'you need provide an {File.__name__} object') - if file.name.split('.')[-1] != 'zip': + # Se for io.BytesIO o file.filename é nulo. + if (file.filename is not None) and (file.filename.split('.')[-1] != 'zip'): raise InvalidFile('the file must be a .zip file') response: Response = await self._http.upload(file) if not kwargs.get('avoid_listener'): diff --git a/squarecloud/http/http_client.py b/squarecloud/http/http_client.py index 19efe94..634454e 100644 --- a/squarecloud/http/http_client.py +++ b/squarecloud/http/http_client.py @@ -54,7 +54,7 @@ async def request(self, route: Router, if route.endpoint in (Endpoint.commit(), Endpoint.upload()): file = kwargs.pop('file') form = aiohttp.FormData() - form.add_field('file', file.bytes, filename=file.name) + form.add_field('file', file.bytes, filename=file.filename) kwargs['data'] = form async with self.__session(headers=headers) as session: async with session.request(url=route.url, method=route.method, diff --git a/squarecloud/square.py b/squarecloud/square.py index faecbf6..b2ada39 100644 --- a/squarecloud/square.py +++ b/squarecloud/square.py @@ -4,19 +4,35 @@ import io import os +from typing import Any + class File: - """File object""" - __slots__ = ( - 'path', - 'name', - 'bytes', - ) - - def __init__(self, path: str): - self.bytes = io.open(path, 'rb') - self.path = path - self.name = os.path.basename(path) - - def __repr__(self): - return f'<{self.__class__.__name__}(name={self.name}, path={self.path})' + """ + File object + + You can use a file already opened or pass the file path. + NOTE: To pass binary data, consider usage of `io.BytesIO`. + """ + + __slots__ = ('bytes', 'filename') + + def __init__( + self, + fp: str | bytes | os.PathLike[Any] | io.BufferedIOBase, + filename: str | None = None + ): + if isinstance(fp, io.IOBase): + if not (fp.seekable() and fp.readable()): + raise ValueError(f'File buffer {fp!r} must be seekable and readable') + self.bytes: io.BufferedIOBase = fp + else: + self.bytes = open(fp, 'rb') + + if filename is None: + if isinstance(fp, str): + _, filename = os.path.split(fp) + else: + filename = getattr(fp, 'name', None) + + self.filename: str | None = filename