diff --git a/LICENSE b/LICENSE index 6f3ad1e..ffdcaaa 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 N0x1s +Copyright (c) 2020 n0x1s (Ilyass El Fatimy) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 2e2121c..0250380 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,55 @@ -# data_b64 +# b64! +[![Python 3.7.1](https://img.shields.io/badge/Python-3.7.1-green.svg)](http://www.python.org/download/) +convert offline/online data to base64 clean, fast and easy -data_b64 is a python module that convert media to base64 - - auto detect media type -> bytes - online media - on desk media - - easy to use - - -### Installation - -data_b64 requires [python3](https://python.org/) to run. - -Install the dependencies. - -```sh -$ pip install data_b64 -``` - -License +what b64 do for you? ---- +* clean, fast and easy +* convert data (image, video, text) to base64 from URL or local or b'string' +* convert base64 to data (image, video, text) +* auto-detect source type all you have to do is inserting the source +* support proxies, custom success code +## install +You can either install from pypi or the source code +1) Using pip +```bash +pip install b64 +``` +2) from the source code +```bash +git clone https://github.com/n0x1s/data_b64 +cd data_b64 +python setup.py install +``` +## How to use + +Let us suppose you have a group of data that you want to convert to base64 or the opposite +```python +>>> from b64 import B64 +### some examples #### +>>> online_image = 'https://avatars3.githubusercontent.com/u/1' +>>> local_image = 'test.jpg' +>>> string = 'hello'.encode() +>>> online_base64 = 'https://pastebin.com/raw/mYPrvzDz' +>>> local_base64 = 'example.txt' +>>> b64_string = b'aGVsbG8=' +``` +1) converting online data +```python +>>> B64(online_image).data # converting image to base64 +> b'iVBORw0KGgoAAAANSUhEUgAAAcwAAAHMCAYAAABY25iGA...' +>>> B64('https://pastebin.com/raw/mYPrvzDz', to='string', codes=[200, 201]).data # you can set the success http codes or use proxies +> b'Hello' +``` +2) converting local data +```python +>>> B64(local_image).data # converting image to base64 +> b'iVBORw0KGgoAAAANSUhEUgAAAcwAAAHMCAYAAABY25iGA...' +>>> B64('example.txt', to='string').data # converting local base64 string to bytes +> b'Hello' +``` +## Todo +I will try to maintain this respiratory and update or add new things to it you are welcome to contribute :relaxed: -MIT - - -**Free Software, Hell Yeah!** +And, as always have a beautiful day! diff --git a/__init__.py b/__init__.py index b6bca53..e69de29 100644 --- a/__init__.py +++ b/__init__.py @@ -1 +0,0 @@ -from data_b64.core import Media2B64 diff --git a/b64/__init__.py b/b64/__init__.py new file mode 100644 index 0000000..0c9ec8e --- /dev/null +++ b/b64/__init__.py @@ -0,0 +1 @@ +from .core import B64 diff --git a/b64/core.py b/b64/core.py new file mode 100644 index 0000000..4b12f64 --- /dev/null +++ b/b64/core.py @@ -0,0 +1,36 @@ +from b64 import utils +import base64 +from urllib import parse +from cached_properties import Property as property + + +class B64: + """ a class to convert online/offline media to base64/text""" + __version__ = '0.4a' + + def __init__(self, source, to='base64', *args, **kwargs): + self.source = source + self.to = to + self._args, self._kwargs = args, kwargs + + def convert(self): + """ a method to handle conversation between base64 and bytes """ + func = base64.b64encode if self.to == 'base64' else base64.b64decode + return func(self.file_bytes) + + @property + def file_bytes(self): + """ cached property for file bytes """ + if isinstance(self.source, bytes): + if not self.source: + raise utils.FileNotFound + return self.source + elif parse.urlparse(self.source).scheme: + r = utils.download_file(self.source, *self._args, **self._kwargs) + del self._args, self._kwargs + return r + return utils.read_file(self.source) + + @property + def data(self): + return self.convert() diff --git a/b64/utils.py b/b64/utils.py new file mode 100644 index 0000000..04e51b3 --- /dev/null +++ b/b64/utils.py @@ -0,0 +1,52 @@ +import os +import requests + + +class FileNotFound(Exception): + """ Exception for file not found """ + + def __init__(self): + msg = ''' + File Not Found, please check your path, permission, and headers + And Try Again''' + super().__init__(msg) + + +def download_file(source, codes=(200, ), chunk=1024, *args, **kwargs) -> bytes: + """ a function to download files from internet to bytes """ + file = bytes() + try: + r = requests.get(source, stream=True, *args, **kwargs) + except Exception as e: + raise FileNotFound + if r.status_code not in codes: + raise FileNotFound + while True: + r.raw.decode_content = True + part = r.raw.read(chunk) + if not part: + break + file += part + return file + + +def read_file(source: str) -> bytes: + """ read local file bytes """ + if os.path.exists(source) and os.path.isfile(source): + with open(source, 'rb') as fobj: + return fobj.read() + raise FileNotFound + + +def exists(source) -> bool: + """ check if the source exists """ + dtype = self._detect_type(source) + if dtype == 'local': + return os.path.exists(source) and os.path.isfile(source) + elif dtype == 'remote': + try: + r = request.urlopen(source) + except Exception as e: + return False + return r.status in code + return bool(source) diff --git a/data_b64/core.py b/data_b64/core.py deleted file mode 100644 index b1d5ab9..0000000 --- a/data_b64/core.py +++ /dev/null @@ -1,98 +0,0 @@ -import os -import base64 -from urllib import request -from urllib import parse -class FileNotFound(Exception): - """ Exception for file not found """ - def __init__(self): - msg = ''' - File Not Found, please check your path, permission, and headers - And Try Again''' - super().__init__(msg) - -class Media2B64: - """ a class to convert online/offline media to base64""" - __version__ = '0.3a' - - def __init__(self, source:str = str(), *args, **kw): - if source: - if not self._exists(source): - raise FileNotFound - self.dtype = self._detect_type(source) - self.data = self.read_data(source, *args, **kw) - - def _transform(self, dest: str = 'base64', data: bytes = bytes()) -> bytes: - """ a method to handle conversation between base64 and bytes - destination parameter takes: - string to convert from base64 to string - b64, anything else to convert from bytes to base64""" - f = base64.b64decode if dest == 'string' else base64.b64encode - if data: - return f(data) - return f(self.data) - - def convert_to(self, dest: str = 'base64', source=None, *args, **kwargs): - """the function that the user call with the data""" - if source: - dtype = self._detect_type(source) - func = self._pickup_method(dtype) - return self._transform(data=func(source), *args, **kwargs) - return self._transform(data=self.data, *args, **kwargs) - - def read_data(self, source: str or bytes, **kw) -> bytes: - """ a method to automatically read bytes based on the source """ - return self._pickup_method(self.dtype)(source, **kw) - - def _download_file(self, source: str, chunk: int = 1024) -> bytes: - """ a method to download files from online to bytes """ - file = bytes() - if not source: - source = self.source - r = request.urlopen(source) - while True: - part = r.read(chunk) - if not part: - break - file += part - return file - - def _read_file(self, source: str) -> bytes: - """ read local file bytes """ - if not source: - source = self.source - with open(source, 'rb') as fobj: - return fobj.read() - - - def _detect_type(self, source: str or bytes) -> str: - """ a method that detect data type """ - if not source and not isinstance(source, bytes): - source = self.source - if isinstance(source, bytes): - return 'bytes' - elif parse.urlparse(source).scheme: - return 'remote' - return 'local' - - def _pickup_method(self, dtype: str or bytes): - """a method to pickup the right function for the data type""" - dtype = dtype if dtype else self.dtype - - if dtype == 'remote': - return self._download_file - elif dtype == 'local': - return self._read_file - return bytes - - def _exists(self, source: str or bytes, code: list = range(200,301)) -> bool: - """ check if the source exists """ - dtype = self._detect_type(source) - if dtype == 'local': - return os.path.exists(source) and os.path.isfile(source) - elif dtype == 'remote': - try: - r = request.urlopen(source) - except Exception as e: - return False - return r.status in code - return bool(source) diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..da4915a --- /dev/null +++ b/setup.py @@ -0,0 +1,24 @@ +from distutils.core import setup +setup( + name='b64', + packages=['b64'], + version='0.1', + license='MIT', + description='convert local/online data to base64 fast, easy and clean', + author='n0x1s', + author_email='n0x1s0x01@gmail.com', + url='https://github.com/n0x1s/data_b64', + download_url='https://github.com/n0x1s/b64/archive/0.1.tar.gz', + keywords=['base64', 'image to base64', 'video to base64', + 'base64 convert'], + classifiers=[ + 'Development Status :: 3 - Alpha', + 'Intended Audience :: Developers', + 'Topic :: Software Development :: Build Tools', + 'License :: OSI Approved :: MIT License', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + ], +)