aplustools


Nameaplustools JSON
Version 1.4.8.5 PyPI version JSON
download
home_pageNone
SummaryA collection of helpful tools
upload_time2024-05-12 15:41:46
maintainerNone
docs_urlNone
authorNone
requires_python>=3.9
licenseGPL-3.0-or-later
keywords general tools app tools beta apt
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # aplustools
[![Active Development](https://img.shields.io/badge/Maintenance%20Level-Actively%20Developed-brightgreen.svg)](https://gist.github.com/cheerfulstoic/d107229326a01ff0f333a1d3476e068d)
[![Build Status](https://github.com/Adalfarus/aplustools/actions/workflows/python-publish.yml/badge.svg)](https://github.com/Adalfarus/aplustools/actions)
[![License: GPL-3.0](https://img.shields.io/github/license/Adalfarus/aplustools)](https://github.com/Adalfarus/aplustools/blob/main/LICENSE)

## Description

aplustools is a simple, user-friendly Python library for performing amazing tasks. It simplifies complex processes, allowing you to achieve more with less code. Developed with a focus on ease of use and efficiency, aplustools is the go-to solution for Python developers looking to enhance their projects.

## Features

- Easy to use
- Highly efficient
- Supports multiple platforms
- Regular updates and support
- Comprehensive documentation

## Installation

You can install aplustools via pip:

```sh
pip install aplustools --upgrade
```

Or clone the repository and install manually:

```sh
git clone https://github.com/Adalfarus/aplustools.git
cd aplustools
python -m build
```

## Usage

Here are a few quick examples of how to use aplustools:

### Search Engine usage
```python
from aplustools.web.search import Search, GoogleSearchCore

# Call the `google_provider` function with a query
searcher = Search(GoogleSearchCore(advanced=True))
results = searcher.search("Cute puppies", num_results=10)

# Print the result
print(results)

from aplustools.web.utils import WebPage

web_page = WebPage(results[0].get("url"))

response = None
if web_page.crawlable:  # Google search does this automatically at the moment
    response = web_page.page.content
print(response)

```

### web requests
```python
from aplustools.web.request import UnifiedRequestHandler, UnifiedRequestHandlerAdvanced
import os

# Default request handler
handler = UnifiedRequestHandler()

# Synchronous request
handler.fetch('http://example.com', async_mode=False)
# Asynchronous request
handler.fetch('http://example.com', async_mode=True)

# Advanced request handler (you can pass extra keyword arguments, and it automatically raises for status)
adv_handler = UnifiedRequestHandlerAdvanced()  # It can also handle image content

# Synchronous GET request
adv_handler.request('GET', 'http://example.com', async_mode=False)
# Asynchronous GET request
adv_handler.request('GET', 'http://example.com', async_mode=True)

folder_path = "./test_data/images"
os.makedirs(folder_path, exist_ok=True)

# Synchronous binary request (e.g., image)
image_content = adv_handler.request('GET', 'http://example.com/image.png', async_mode=False, return_type='binary')
with open(os.path.join(folder_path, './image.png'), 'wb') as file:
    file.write(image_content)

# Asynchronous binary request (e.g., image)
image_content_async = adv_handler.request('GET', 'http://example.com/image.png', async_mode=True, return_type='binary')
with open(os.path.join(folder_path, './image_async.png'), 'wb') as file:
    file.write(image_content_async)

```

### ImageManager
````python
from aplustools.data.imagetools import ImageManager, OnlineImage
import os

os.makedirs("./test", exist_ok=True)
manager = ImageManager("./test", use_async=True)
image_index = manager.add_image(OnlineImage, "somewhere.com/image.jpg")

manager.execute_func(image_index, "download_image")
manager.execute_func(image_index, "convert_to_grayscale")
manager.execute_func(image_index, "apply_filter")  # Default is blur
manager.execute_func(image_index, "rotate_image", 12)
manager.execute_func(image_index, "save_image_to_disk")  # Overwrites downloaded file

````

### ImageTypes
```python
from aplustools.data.imagetools import OnlineImage, OfflineImage, ImageFilter, SVGCompatibleImage
import os

# Setup
folder_path = "./images"
os.makedirs(folder_path, exist_ok=True)
test_url = "someImage.url"
base64_image_str = ("data:image/jpeg;base64,...")

# Test downloading an online image
online_image = OnlineImage(current_url=test_url, base_location=folder_path, one_time=True)
download_result = online_image.download_image(folder_path, online_image.current_url, "downloaded_image", "jpg")
if not download_result[0]:
    raise Exception("Failed to download image.")
else:
    online_image.convert_to_grayscale()
    online_image.save_image_to_disk(os.path.join(folder_path, "image.png"))

# Test loading and saving a base64 image with OfflineImage
offline_image = OfflineImage(data=base64_image_str, base_location=folder_path)
save_result = offline_image.base64(folder_path, "base64_image", "png")
if not save_result:
    raise Exception("Failed to save base64 image.")

# Test image transformations
offline_image.resize_image((100, 100))
offline_image.rotate_image(45)
offline_image.convert_to_grayscale()
offline_image.apply_filter(ImageFilter.BLUR)
offline_image.save_image_to_disk(os.path.join(folder_path, "transformed_image.png"))

# Example svg image usage
image_processor = SVGCompatibleImage("someSvg.svg", 300,
                                     (667, 800), magick_path=r".\ImageMagick",
                                     base_location='./')
image_processor.save_image_to_disk()


from aplustools.io.environment import absolute_path, remv, copy

a_img_path = absolute_path(os.path.join(folder_path, "downloaded_image.jpg"))

copy(a_img_path, str(folder_path) + "downloaded_image" + " - Copy.jpg")

remv(a_img_path)  # Remove the original image
remv(folder_path)  # Remove the base directory

```

### Faker
```python
from aplustools.data.faker import TestDataGenerator

test_data = TestDataGenerator()
print(test_data.generate_random_identity())

print("\n", end="")
print(test_data.generate_random_name())
print(test_data.generate_random_email())
print(test_data.generate_random_password())
print(test_data.generate_random_phone_number())
print(test_data.generate_random_address())
print(test_data.generate_random_birth_date())

```

### Dummy
```python
from aplustools.utils.dummy import Dummy3  # Dummy3 is for Python 3
import math

dummy = Dummy3()

# Do a bunch of operations that would normally throw errors
dummy.attr.func("", int3="")
dummy["Hello"] = 1
del dummy[1]
reversed(dummy)
if not "Dummy" in dummy:
    dummy.keys = ["1"]
print(dummy.keys + dummy)
var1 = +dummy
var2 = -dummy
var3 = ~dummy
print(var1, var2, var3)

hash(dummy)
abs(dummy)
round(dummy)
complex(dummy)
oct(dummy)
repr(dummy)
bytes(dummy)
format(dummy, "DD")

math.trunc(dummy)
dummy << dummy
dummy >> dummy
dummy -= 1_000_000
num = 1
num *= dummy

if dummy:
    print(True)
else:
    print(False)

for x in dummy:
    print(x)

type(dummy)
print(dummy, "->", int(dummy), list(dummy), tuple(dummy), float(dummy))

```

### Hasher
```python
from aplustools.utils.hasher import hashed_latest, hashed_wrapper_latest, reducer, big_reducer, num_hasher

inp = "Hello beautiful world, how are you today, lovely star?"
inp2 = "Hello World, kitty"

desired_length = 64

hashed_inp = hashed_wrapper_latest(inp, desired_length, hash_func=hashed_latest)
hashed_inp2 = hashed_wrapper_latest(inp2, desired_length, hash_func=hashed_latest)

print(f"{inp} ({len(inp)}) -> {hashed_inp} ({len(hashed_inp)})\n{inp2} ({len(inp2)}) -> {hashed_inp2} ({len(hashed_inp2)})")

num_hashed_inp = num_hasher(inp, desired_length)
num_hashed_inp2 = num_hasher(inp2, desired_length)

print(f"{inp} ({len(inp)}) -> {num_hashed_inp} ({len(num_hashed_inp)})\n{inp2} ({len(inp2)}) -> {num_hashed_inp2} ({len(num_hashed_inp2)})")

acceptable_chars = range(100, 200)

num_hashed_inp_uni = num_hasher(inp, desired_length, acceptable_chars)
num_hashed_inp_uni_2 = num_hasher(inp2, desired_length, acceptable_chars)

print(f"{inp} ({len(inp)}) -> {num_hashed_inp_uni} ({len(num_hashed_inp_uni)})\n{inp2} ({len(inp2)}) -> {num_hashed_inp_uni_2} ({len(num_hashed_inp_uni_2)})")

```

### GenPass
```python
from aplustools.utils.genpass import SecurePasswordManager, GeneratePasswords

manager = SecurePasswordManager()
password = manager.generate_ratio_based_password_v2(length=26, letters_ratio=0.5, numbers_ratio=0.3,
                                                    punctuations_ratio=0.2, exclude_similar=True)
manager.add_password("example.com", "json-the-greatest", password)
manager.store_in_buffer("example.com", 0)  # Stores unencrypted password in a buffer
print(manager.get_password("example.com"), "|", manager.use_from_buffer(0))  # for faster access.

print(GeneratePasswords.generate_custom_sentence_based_password_v1(
    "Exploring the unknown -- discovering new horizons...", random_case=True, extra_char="_",
    char_position="keep" or 0, num_length=5, special_chars_length=2))
# "keep" just sets it to 0

# These classes are mostly meant for secure interprocess bidirectional
# communication using networks.
from aplustools.utils.genpass import ControlCodeProtocol, SecureSocketServer, SecureSocketClient

# Initialize the protocol
prot = ControlCodeProtocol()

# Create a client and a server
client = SecureSocketClient(prot)
sock = client.get_socket()
server = SecureSocketServer(sock, prot)

# Start key exchange and communication between server and client
client.start_and_exchange_keys()  # Client has to start first
server.start_and_exchange_keys()

# Client sends a message and a control code to the server
client.add_control_code("shutdown")
client.add_message("HELLO SERVER")
client.sendall()  # The message is still received as it sends one chunk here
# which then get's decoded in one piece. The decoder decodes everything
# into chunks and control codes are always put behind messages.

# Server shuts down the client connection
server.shutdown_client()
print("DONE1")

# There are also classes for one directional communication that are
# more integrated.
from aplustools.utils.genpass import ControlCodeProtocol, ServerMessageHandler, ClientMessageHandler
import threading

prot = ControlCodeProtocol()

# Create message handlers for server and client
encoder = ClientMessageHandler(prot)

# Make a connection using the clients host and chosen port
connection = encoder.get_socket()

decoder = ServerMessageHandler(connection, prot)

# Client prepares and sends a message
encoder.add_message("Hello Server")
encoder.send_control_message("shutdown")

# Server receives and processes each chunk
encoder.start()
threading.Thread(decoder.listen_for_messages()).start()  # Blocking
encoder.flush()  # Blocking until connection is established

```

### Github-Updater
```python
from aplustools.data.updaters import GithubUpdater, VersionNumber
from aplustools.io.environment import get_temp
from aplustools import set_dir_to_ex
import sys
import os

set_dir_to_ex()

__version__ = VersionNumber("0.0.1")

# Initialize an updater
updater = GithubUpdater("Adalfarus", "unicode-writer", "py")  # If you want to use exe
latest_version = updater.get_latest_tag_version()             # you need to compile them
                                                              # yourself, otherwise it
# Check if an update is needed                                # won't work
if __version__ >= latest_version:
    sys.exit()

# Updater method
path, zip_path = os.path.join(os.getcwd(), "update"), os.path.join(get_temp(), f"apt-update_{latest_version}")

os.makedirs(path, exist_ok=True)
os.makedirs(zip_path, exist_ok=True)

# Start the update in a separate thread
update_thread = updater.update(path, zip_path, latest_version, implementation="none", 
                               host="localhost", port=1264, non_blocking=True, wait_for_connection=True)
update_thread.start()

# Receive the update status generator and print them
progress_bar = 1
for i in updater.receive_update_status():
    print(f"{i}%", end=f" PB{progress_bar}\n")
    if i == 100:
        progress_bar += 1  # Switch to second progress bar, when the downloading is finished
update_thread.join()

```

### ArguMint
```python
from aplustools.package.argumint import ArgStruct, ArguMint
from typing import Literal
import sys


def sorry(*args, **kwargs):
    print("Not implemented yet, sorry!")


def help_text():
    print("Build -> dir/file or help.")


def build_file(path: Literal["./main.py", "./file.py"] = "./main.py", num: int = 0):
    """
    build_file
    :param path: The path to the file that should be built.
    :param num:
    :return None:
    """
    print(f"Building file {path} ..., {num}")


from aplustools.package import timid

timer = timid.TimidTimer()

arg_struct = {'apt': {'build': {'file': {}, 'dir': {'main': {}, 'all': {}}}, 'help': {}}}

# Example usage
builder = ArgStruct()
builder.add_command("apt")
builder.add_nested_command("apt", "build", "file")

builder.add_nested_command("apt.build", "dir", {'main': {}, 'all': {}})
# builder.add_subcommand("apt.build", "dir")
# builder.add_nested_command("apt.build.dir", "main")
# builder.add_nested_command("apt.build.dir", "all")

builder.add_command("apt.help")
# builder.add_nested_command("apt", "help")

print(builder.get_structure())  # Best to cache this for better times (by ~15 microseconds)

parser = ArguMint(default_endpoint=sorry, arg_struct=arg_struct)
parser.add_endpoint("apt.help", help_text)

parser.add_endpoint("apt.build.file", build_file)

sys.argv[0] = "apt"

# Testing
# sys.argv = ["apt", "help"]
# sys.argv = ["apt", "build", "file", "./file.py", "--num=19"]
parser.parse_cli(sys, "native_light")
print(timer.end())

```

### compressor
```python
from aplustools.data.compressor import FileContainerV3, BrotliChunkCompressor
import os


compressor = BrotliChunkCompressor()
container = FileContainerV3(compressor, block_size=2048*2048)

image_data = {}
for file in os.listdir("./images"):
    if file.lower().endswith(".png"):
        with open(os.path.join("./images", file), "rb") as f:
            image_file_data = b''.join(f.readlines())
            image_data[file] = image_file_data

for file_name, image in image_data.items():
    container.add_file(file_name, image)

# Get the compressed data
compressed_data = container.get_compressed_container()

print("Compression done")

with open("./files.bin", "wb") as f:
    f.write(compressed_data)

print("Wrote bin")

# To extract a specific file from the compressed data
try:
    decompressed_images = []
    for i in range(len(image_data)):
        decompressed_image = container.extract_file(compressed_data, i)
        decompressed_images.append(decompressed_image)
except Exception as e:
    print("Indexing not possible, error", e, "\n")
    decompressed_images = []
    for file_name in image_data.keys():
        decompressed_image = container.extract_file(compressed_data, file_name)
        decompressed_images.append(decompressed_image)
compression_ratio = len(compressed_data) / sum(len(x) for x in image_data.values())

print(f"Original size: {sum(len(x) for x in image_data.values())} bytes")
print(f"Compressed size: {len(compressed_data)} bytes")
print(f"Compression ratio: {compression_ratio:.2f}")

for i, decompressed_image in enumerate(decompressed_images):
    with open(f"./decompressed_images/image{i}.png", "wb") as f:
        f.write(decompressed_image)

```

### Logger
```python
from aplustools.io import environment as env
from aplustools.io import loggers

# Set the current working directory to the main script or executable
env.set_working_dir_to_main_script_location()

# Create an instance of Logger
p_logger = loggers.PrintLogger("my_logs_file.log", show_time=True, capture_print=False, 
                     overwrite_print=True, print_passthrough=False, print_log_to_stdout=True)
# Shows the time in the logs (Like this [12:33:21]) and overwrites the normal sys.stdout

# Call the `monitor_stdout` method and pass the logger object, this will overwrite sys.stdout from Text I/O to the logger object
logger = loggers.monitor_stdout(logger=p_logger) # Return sys.stdout, so you can make sure it worked

# Log something
p_logger.log("Hello, world!")

# Print something, it won't get captured or displayed
print("Hello, beautiful world!")

# Close the Logger object (returns sys.stdout to it's normal state)
p_logger.close()

```
(If you want to ensure that all dependencies are installed please run `upype import aplustools; aplustools.install_all_dependencies()`)
(Correct shortform for aplustools is apt, so please use ```import aplustools as apt``` for consistency)

There are multiple clis added through this package:

### pype (python pipe)
```bash
C:\Users\user_>pype
Enter Python expression: 1 + 2
3

C:\Users\user_>pype 1 // 3
0
```
### upype (unified python pipe)
```bash
C:\Users\user_>upype import aplustools; print(aplustools.__version__)
1.4.4

C:\Users\user_>upype
Enter Python code (type 'end' on a new line to finish):
... class Test:
...     def hello_word(self):
...             print("Hello, you!")
... test = Test()
... test.hello_word()
... end
Hello, you!
```
These can also be used in e.g. batch files like this
```batch
@echo off
set /p id=Enter ID: 
upype from aplustools.utils.genpass import GeneratePasswords; print(GeneratePasswords.generate_custom_sentence_based_password_v1("""%id%""", random_case=True, extra_char="""_""", char_position=0, num_length=5, special_chars_length=2))
pause

```

### apt
Can currently run tests with ```apt tests run``` and show a basic help using ```apt help```.


For more detailed usage and examples, check out our [documentation](https://github.com/adalfarus/aplustools/wiki).

## Naming convention, dependencies and more
[PEP 8 -- Style Guide for Python Code](https://peps.python.org/pep-0008/#naming-conventions)

For modules I use 'lowercase', classes are 'CapitalizedWords' and functions and methods are 'lower_case_with_underscores'.

Dependencies (except for the standard libraries) are: 
- [`none`]
  - data.database
  - io.environment
  - io.loggers
  - data.faker
  - utils.dummy
  - utils.hasher
  - package.lazy_loader
  - package.timid
- [`requests`]
  - data.github-updater-none
  - data.updaters
  - data.github-updater-cmd
- data.github-updater-gui - [`requests`, `PySide6`]
- data.imagetools - [`Pillow`, `aiohttp`, `requests`, `wand`]
- data.advanced_imagetools - [`opencv-python`, `aiohttp`, `wand`, `pillow_heif`]
- web.search, web.utils - [`requests`, `BeautifulSoup4`]
- utils.genpass - [`cryptography`]
- web.request - [`requests`, `aiohttp`]
- utils.compressor - [`brotli`, `zstandard`, `py7zr`]
- io.gui - [`PySide6`]

Sub-Modules that may be removed in future updates due to being hard to support or simply unneeded.

- database (maybe unneeded and hard to support if more dbs are added -> new_database is being developed)
- loggers (maybe unneeded)

## Contributing

We welcome contributions! Please see our [contributing guidelines](https://github.com/adalfarus/aplustools/blob/main/CONTRIBUTING.md) for more details on how you can contribute to aplustools.

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
4. Push to the branch (`git push origin feature/AmazingFeature`)
5. Open a pull request

## License

aplustools is licensed under the GPL-3.0 License - see the [LICENSE](https://github.com/adalfarus/aplustools/blob/main/LICENSE) file for details.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "aplustools",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.9",
    "maintainer_email": "Cariel Becker <cariel.becker@gmx.de>",
    "keywords": "general, tools, app tools, beta, apt",
    "author": null,
    "author_email": "Cariel Becker <cariel.becker@gmx.de>",
    "download_url": "https://files.pythonhosted.org/packages/e1/f7/88582df93cfb29be0a81019b08e8503f28ce8607898f457502b9b7974e4e/aplustools-1.4.8.5.tar.gz",
    "platform": null,
    "description": "# aplustools\n[![Active Development](https://img.shields.io/badge/Maintenance%20Level-Actively%20Developed-brightgreen.svg)](https://gist.github.com/cheerfulstoic/d107229326a01ff0f333a1d3476e068d)\n[![Build Status](https://github.com/Adalfarus/aplustools/actions/workflows/python-publish.yml/badge.svg)](https://github.com/Adalfarus/aplustools/actions)\n[![License: GPL-3.0](https://img.shields.io/github/license/Adalfarus/aplustools)](https://github.com/Adalfarus/aplustools/blob/main/LICENSE)\n\n## Description\n\naplustools is a simple, user-friendly Python library for performing amazing tasks. It simplifies complex processes, allowing you to achieve more with less code. Developed with a focus on ease of use and efficiency, aplustools is the go-to solution for Python developers looking to enhance their projects.\n\n## Features\n\n- Easy to use\n- Highly efficient\n- Supports multiple platforms\n- Regular updates and support\n- Comprehensive documentation\n\n## Installation\n\nYou can install aplustools via pip:\n\n```sh\npip install aplustools --upgrade\n```\n\nOr clone the repository and install manually:\n\n```sh\ngit clone https://github.com/Adalfarus/aplustools.git\ncd aplustools\npython -m build\n```\n\n## Usage\n\nHere are a few quick examples of how to use aplustools:\n\n### Search Engine usage\n```python\nfrom aplustools.web.search import Search, GoogleSearchCore\n\n# Call the `google_provider` function with a query\nsearcher = Search(GoogleSearchCore(advanced=True))\nresults = searcher.search(\"Cute puppies\", num_results=10)\n\n# Print the result\nprint(results)\n\nfrom aplustools.web.utils import WebPage\n\nweb_page = WebPage(results[0].get(\"url\"))\n\nresponse = None\nif web_page.crawlable:  # Google search does this automatically at the moment\n    response = web_page.page.content\nprint(response)\n\n```\n\n### web requests\n```python\nfrom aplustools.web.request import UnifiedRequestHandler, UnifiedRequestHandlerAdvanced\nimport os\n\n# Default request handler\nhandler = UnifiedRequestHandler()\n\n# Synchronous request\nhandler.fetch('http://example.com', async_mode=False)\n# Asynchronous request\nhandler.fetch('http://example.com', async_mode=True)\n\n# Advanced request handler (you can pass extra keyword arguments, and it automatically raises for status)\nadv_handler = UnifiedRequestHandlerAdvanced()  # It can also handle image content\n\n# Synchronous GET request\nadv_handler.request('GET', 'http://example.com', async_mode=False)\n# Asynchronous GET request\nadv_handler.request('GET', 'http://example.com', async_mode=True)\n\nfolder_path = \"./test_data/images\"\nos.makedirs(folder_path, exist_ok=True)\n\n# Synchronous binary request (e.g., image)\nimage_content = adv_handler.request('GET', 'http://example.com/image.png', async_mode=False, return_type='binary')\nwith open(os.path.join(folder_path, './image.png'), 'wb') as file:\n    file.write(image_content)\n\n# Asynchronous binary request (e.g., image)\nimage_content_async = adv_handler.request('GET', 'http://example.com/image.png', async_mode=True, return_type='binary')\nwith open(os.path.join(folder_path, './image_async.png'), 'wb') as file:\n    file.write(image_content_async)\n\n```\n\n### ImageManager\n````python\nfrom aplustools.data.imagetools import ImageManager, OnlineImage\nimport os\n\nos.makedirs(\"./test\", exist_ok=True)\nmanager = ImageManager(\"./test\", use_async=True)\nimage_index = manager.add_image(OnlineImage, \"somewhere.com/image.jpg\")\n\nmanager.execute_func(image_index, \"download_image\")\nmanager.execute_func(image_index, \"convert_to_grayscale\")\nmanager.execute_func(image_index, \"apply_filter\")  # Default is blur\nmanager.execute_func(image_index, \"rotate_image\", 12)\nmanager.execute_func(image_index, \"save_image_to_disk\")  # Overwrites downloaded file\n\n````\n\n### ImageTypes\n```python\nfrom aplustools.data.imagetools import OnlineImage, OfflineImage, ImageFilter, SVGCompatibleImage\nimport os\n\n# Setup\nfolder_path = \"./images\"\nos.makedirs(folder_path, exist_ok=True)\ntest_url = \"someImage.url\"\nbase64_image_str = (\"data:image/jpeg;base64,...\")\n\n# Test downloading an online image\nonline_image = OnlineImage(current_url=test_url, base_location=folder_path, one_time=True)\ndownload_result = online_image.download_image(folder_path, online_image.current_url, \"downloaded_image\", \"jpg\")\nif not download_result[0]:\n    raise Exception(\"Failed to download image.\")\nelse:\n    online_image.convert_to_grayscale()\n    online_image.save_image_to_disk(os.path.join(folder_path, \"image.png\"))\n\n# Test loading and saving a base64 image with OfflineImage\noffline_image = OfflineImage(data=base64_image_str, base_location=folder_path)\nsave_result = offline_image.base64(folder_path, \"base64_image\", \"png\")\nif not save_result:\n    raise Exception(\"Failed to save base64 image.\")\n\n# Test image transformations\noffline_image.resize_image((100, 100))\noffline_image.rotate_image(45)\noffline_image.convert_to_grayscale()\noffline_image.apply_filter(ImageFilter.BLUR)\noffline_image.save_image_to_disk(os.path.join(folder_path, \"transformed_image.png\"))\n\n# Example svg image usage\nimage_processor = SVGCompatibleImage(\"someSvg.svg\", 300,\n                                     (667, 800), magick_path=r\".\\ImageMagick\",\n                                     base_location='./')\nimage_processor.save_image_to_disk()\n\n\nfrom aplustools.io.environment import absolute_path, remv, copy\n\na_img_path = absolute_path(os.path.join(folder_path, \"downloaded_image.jpg\"))\n\ncopy(a_img_path, str(folder_path) + \"downloaded_image\" + \" - Copy.jpg\")\n\nremv(a_img_path)  # Remove the original image\nremv(folder_path)  # Remove the base directory\n\n```\n\n### Faker\n```python\nfrom aplustools.data.faker import TestDataGenerator\n\ntest_data = TestDataGenerator()\nprint(test_data.generate_random_identity())\n\nprint(\"\\n\", end=\"\")\nprint(test_data.generate_random_name())\nprint(test_data.generate_random_email())\nprint(test_data.generate_random_password())\nprint(test_data.generate_random_phone_number())\nprint(test_data.generate_random_address())\nprint(test_data.generate_random_birth_date())\n\n```\n\n### Dummy\n```python\nfrom aplustools.utils.dummy import Dummy3  # Dummy3 is for Python 3\nimport math\n\ndummy = Dummy3()\n\n# Do a bunch of operations that would normally throw errors\ndummy.attr.func(\"\", int3=\"\")\ndummy[\"Hello\"] = 1\ndel dummy[1]\nreversed(dummy)\nif not \"Dummy\" in dummy:\n    dummy.keys = [\"1\"]\nprint(dummy.keys + dummy)\nvar1 = +dummy\nvar2 = -dummy\nvar3 = ~dummy\nprint(var1, var2, var3)\n\nhash(dummy)\nabs(dummy)\nround(dummy)\ncomplex(dummy)\noct(dummy)\nrepr(dummy)\nbytes(dummy)\nformat(dummy, \"DD\")\n\nmath.trunc(dummy)\ndummy << dummy\ndummy >> dummy\ndummy -= 1_000_000\nnum = 1\nnum *= dummy\n\nif dummy:\n    print(True)\nelse:\n    print(False)\n\nfor x in dummy:\n    print(x)\n\ntype(dummy)\nprint(dummy, \"->\", int(dummy), list(dummy), tuple(dummy), float(dummy))\n\n```\n\n### Hasher\n```python\nfrom aplustools.utils.hasher import hashed_latest, hashed_wrapper_latest, reducer, big_reducer, num_hasher\n\ninp = \"Hello beautiful world, how are you today, lovely star?\"\ninp2 = \"Hello World, kitty\"\n\ndesired_length = 64\n\nhashed_inp = hashed_wrapper_latest(inp, desired_length, hash_func=hashed_latest)\nhashed_inp2 = hashed_wrapper_latest(inp2, desired_length, hash_func=hashed_latest)\n\nprint(f\"{inp} ({len(inp)}) -> {hashed_inp} ({len(hashed_inp)})\\n{inp2} ({len(inp2)}) -> {hashed_inp2} ({len(hashed_inp2)})\")\n\nnum_hashed_inp = num_hasher(inp, desired_length)\nnum_hashed_inp2 = num_hasher(inp2, desired_length)\n\nprint(f\"{inp} ({len(inp)}) -> {num_hashed_inp} ({len(num_hashed_inp)})\\n{inp2} ({len(inp2)}) -> {num_hashed_inp2} ({len(num_hashed_inp2)})\")\n\nacceptable_chars = range(100, 200)\n\nnum_hashed_inp_uni = num_hasher(inp, desired_length, acceptable_chars)\nnum_hashed_inp_uni_2 = num_hasher(inp2, desired_length, acceptable_chars)\n\nprint(f\"{inp} ({len(inp)}) -> {num_hashed_inp_uni} ({len(num_hashed_inp_uni)})\\n{inp2} ({len(inp2)}) -> {num_hashed_inp_uni_2} ({len(num_hashed_inp_uni_2)})\")\n\n```\n\n### GenPass\n```python\nfrom aplustools.utils.genpass import SecurePasswordManager, GeneratePasswords\n\nmanager = SecurePasswordManager()\npassword = manager.generate_ratio_based_password_v2(length=26, letters_ratio=0.5, numbers_ratio=0.3,\n                                                    punctuations_ratio=0.2, exclude_similar=True)\nmanager.add_password(\"example.com\", \"json-the-greatest\", password)\nmanager.store_in_buffer(\"example.com\", 0)  # Stores unencrypted password in a buffer\nprint(manager.get_password(\"example.com\"), \"|\", manager.use_from_buffer(0))  # for faster access.\n\nprint(GeneratePasswords.generate_custom_sentence_based_password_v1(\n    \"Exploring the unknown -- discovering new horizons...\", random_case=True, extra_char=\"_\",\n    char_position=\"keep\" or 0, num_length=5, special_chars_length=2))\n# \"keep\" just sets it to 0\n\n# These classes are mostly meant for secure interprocess bidirectional\n# communication using networks.\nfrom aplustools.utils.genpass import ControlCodeProtocol, SecureSocketServer, SecureSocketClient\n\n# Initialize the protocol\nprot = ControlCodeProtocol()\n\n# Create a client and a server\nclient = SecureSocketClient(prot)\nsock = client.get_socket()\nserver = SecureSocketServer(sock, prot)\n\n# Start key exchange and communication between server and client\nclient.start_and_exchange_keys()  # Client has to start first\nserver.start_and_exchange_keys()\n\n# Client sends a message and a control code to the server\nclient.add_control_code(\"shutdown\")\nclient.add_message(\"HELLO SERVER\")\nclient.sendall()  # The message is still received as it sends one chunk here\n# which then get's decoded in one piece. The decoder decodes everything\n# into chunks and control codes are always put behind messages.\n\n# Server shuts down the client connection\nserver.shutdown_client()\nprint(\"DONE1\")\n\n# There are also classes for one directional communication that are\n# more integrated.\nfrom aplustools.utils.genpass import ControlCodeProtocol, ServerMessageHandler, ClientMessageHandler\nimport threading\n\nprot = ControlCodeProtocol()\n\n# Create message handlers for server and client\nencoder = ClientMessageHandler(prot)\n\n# Make a connection using the clients host and chosen port\nconnection = encoder.get_socket()\n\ndecoder = ServerMessageHandler(connection, prot)\n\n# Client prepares and sends a message\nencoder.add_message(\"Hello Server\")\nencoder.send_control_message(\"shutdown\")\n\n# Server receives and processes each chunk\nencoder.start()\nthreading.Thread(decoder.listen_for_messages()).start()  # Blocking\nencoder.flush()  # Blocking until connection is established\n\n```\n\n### Github-Updater\n```python\nfrom aplustools.data.updaters import GithubUpdater, VersionNumber\nfrom aplustools.io.environment import get_temp\nfrom aplustools import set_dir_to_ex\nimport sys\nimport os\n\nset_dir_to_ex()\n\n__version__ = VersionNumber(\"0.0.1\")\n\n# Initialize an updater\nupdater = GithubUpdater(\"Adalfarus\", \"unicode-writer\", \"py\")  # If you want to use exe\nlatest_version = updater.get_latest_tag_version()             # you need to compile them\n                                                              # yourself, otherwise it\n# Check if an update is needed                                # won't work\nif __version__ >= latest_version:\n    sys.exit()\n\n# Updater method\npath, zip_path = os.path.join(os.getcwd(), \"update\"), os.path.join(get_temp(), f\"apt-update_{latest_version}\")\n\nos.makedirs(path, exist_ok=True)\nos.makedirs(zip_path, exist_ok=True)\n\n# Start the update in a separate thread\nupdate_thread = updater.update(path, zip_path, latest_version, implementation=\"none\", \n                               host=\"localhost\", port=1264, non_blocking=True, wait_for_connection=True)\nupdate_thread.start()\n\n# Receive the update status generator and print them\nprogress_bar = 1\nfor i in updater.receive_update_status():\n    print(f\"{i}%\", end=f\" PB{progress_bar}\\n\")\n    if i == 100:\n        progress_bar += 1  # Switch to second progress bar, when the downloading is finished\nupdate_thread.join()\n\n```\n\n### ArguMint\n```python\nfrom aplustools.package.argumint import ArgStruct, ArguMint\nfrom typing import Literal\nimport sys\n\n\ndef sorry(*args, **kwargs):\n    print(\"Not implemented yet, sorry!\")\n\n\ndef help_text():\n    print(\"Build -> dir/file or help.\")\n\n\ndef build_file(path: Literal[\"./main.py\", \"./file.py\"] = \"./main.py\", num: int = 0):\n    \"\"\"\n    build_file\n    :param path: The path to the file that should be built.\n    :param num:\n    :return None:\n    \"\"\"\n    print(f\"Building file {path} ..., {num}\")\n\n\nfrom aplustools.package import timid\n\ntimer = timid.TimidTimer()\n\narg_struct = {'apt': {'build': {'file': {}, 'dir': {'main': {}, 'all': {}}}, 'help': {}}}\n\n# Example usage\nbuilder = ArgStruct()\nbuilder.add_command(\"apt\")\nbuilder.add_nested_command(\"apt\", \"build\", \"file\")\n\nbuilder.add_nested_command(\"apt.build\", \"dir\", {'main': {}, 'all': {}})\n# builder.add_subcommand(\"apt.build\", \"dir\")\n# builder.add_nested_command(\"apt.build.dir\", \"main\")\n# builder.add_nested_command(\"apt.build.dir\", \"all\")\n\nbuilder.add_command(\"apt.help\")\n# builder.add_nested_command(\"apt\", \"help\")\n\nprint(builder.get_structure())  # Best to cache this for better times (by ~15 microseconds)\n\nparser = ArguMint(default_endpoint=sorry, arg_struct=arg_struct)\nparser.add_endpoint(\"apt.help\", help_text)\n\nparser.add_endpoint(\"apt.build.file\", build_file)\n\nsys.argv[0] = \"apt\"\n\n# Testing\n# sys.argv = [\"apt\", \"help\"]\n# sys.argv = [\"apt\", \"build\", \"file\", \"./file.py\", \"--num=19\"]\nparser.parse_cli(sys, \"native_light\")\nprint(timer.end())\n\n```\n\n### compressor\n```python\nfrom aplustools.data.compressor import FileContainerV3, BrotliChunkCompressor\nimport os\n\n\ncompressor = BrotliChunkCompressor()\ncontainer = FileContainerV3(compressor, block_size=2048*2048)\n\nimage_data = {}\nfor file in os.listdir(\"./images\"):\n    if file.lower().endswith(\".png\"):\n        with open(os.path.join(\"./images\", file), \"rb\") as f:\n            image_file_data = b''.join(f.readlines())\n            image_data[file] = image_file_data\n\nfor file_name, image in image_data.items():\n    container.add_file(file_name, image)\n\n# Get the compressed data\ncompressed_data = container.get_compressed_container()\n\nprint(\"Compression done\")\n\nwith open(\"./files.bin\", \"wb\") as f:\n    f.write(compressed_data)\n\nprint(\"Wrote bin\")\n\n# To extract a specific file from the compressed data\ntry:\n    decompressed_images = []\n    for i in range(len(image_data)):\n        decompressed_image = container.extract_file(compressed_data, i)\n        decompressed_images.append(decompressed_image)\nexcept Exception as e:\n    print(\"Indexing not possible, error\", e, \"\\n\")\n    decompressed_images = []\n    for file_name in image_data.keys():\n        decompressed_image = container.extract_file(compressed_data, file_name)\n        decompressed_images.append(decompressed_image)\ncompression_ratio = len(compressed_data) / sum(len(x) for x in image_data.values())\n\nprint(f\"Original size: {sum(len(x) for x in image_data.values())} bytes\")\nprint(f\"Compressed size: {len(compressed_data)} bytes\")\nprint(f\"Compression ratio: {compression_ratio:.2f}\")\n\nfor i, decompressed_image in enumerate(decompressed_images):\n    with open(f\"./decompressed_images/image{i}.png\", \"wb\") as f:\n        f.write(decompressed_image)\n\n```\n\n### Logger\n```python\nfrom aplustools.io import environment as env\nfrom aplustools.io import loggers\n\n# Set the current working directory to the main script or executable\nenv.set_working_dir_to_main_script_location()\n\n# Create an instance of Logger\np_logger = loggers.PrintLogger(\"my_logs_file.log\", show_time=True, capture_print=False, \n                     overwrite_print=True, print_passthrough=False, print_log_to_stdout=True)\n# Shows the time in the logs (Like this [12:33:21]) and overwrites the normal sys.stdout\n\n# Call the `monitor_stdout` method and pass the logger object, this will overwrite sys.stdout from Text I/O to the logger object\nlogger = loggers.monitor_stdout(logger=p_logger) # Return sys.stdout, so you can make sure it worked\n\n# Log something\np_logger.log(\"Hello, world!\")\n\n# Print something, it won't get captured or displayed\nprint(\"Hello, beautiful world!\")\n\n# Close the Logger object (returns sys.stdout to it's normal state)\np_logger.close()\n\n```\n(If you want to ensure that all dependencies are installed please run `upype import aplustools; aplustools.install_all_dependencies()`)\n(Correct shortform for aplustools is apt, so please use ```import aplustools as apt``` for consistency)\n\nThere are multiple clis added through this package:\n\n### pype (python pipe)\n```bash\nC:\\Users\\user_>pype\nEnter Python expression: 1 + 2\n3\n\nC:\\Users\\user_>pype 1 // 3\n0\n```\n### upype (unified python pipe)\n```bash\nC:\\Users\\user_>upype import aplustools; print(aplustools.__version__)\n1.4.4\n\nC:\\Users\\user_>upype\nEnter Python code (type 'end' on a new line to finish):\n... class Test:\n...     def hello_word(self):\n...             print(\"Hello, you!\")\n... test = Test()\n... test.hello_word()\n... end\nHello, you!\n```\nThese can also be used in e.g. batch files like this\n```batch\n@echo off\nset /p id=Enter ID: \nupype from aplustools.utils.genpass import GeneratePasswords; print(GeneratePasswords.generate_custom_sentence_based_password_v1(\"\"\"%id%\"\"\", random_case=True, extra_char=\"\"\"_\"\"\", char_position=0, num_length=5, special_chars_length=2))\npause\n\n```\n\n### apt\nCan currently run tests with ```apt tests run``` and show a basic help using ```apt help```.\n\n\nFor more detailed usage and examples, check out our [documentation](https://github.com/adalfarus/aplustools/wiki).\n\n## Naming convention, dependencies and more\n[PEP 8 -- Style Guide for Python Code](https://peps.python.org/pep-0008/#naming-conventions)\n\nFor modules I use 'lowercase', classes are 'CapitalizedWords' and functions and methods are 'lower_case_with_underscores'.\n\nDependencies (except for the standard libraries) are: \n- [`none`]\n  - data.database\n  - io.environment\n  - io.loggers\n  - data.faker\n  - utils.dummy\n  - utils.hasher\n  - package.lazy_loader\n  - package.timid\n- [`requests`]\n  - data.github-updater-none\n  - data.updaters\n  - data.github-updater-cmd\n- data.github-updater-gui - [`requests`, `PySide6`]\n- data.imagetools - [`Pillow`, `aiohttp`, `requests`, `wand`]\n- data.advanced_imagetools - [`opencv-python`, `aiohttp`, `wand`, `pillow_heif`]\n- web.search, web.utils - [`requests`, `BeautifulSoup4`]\n- utils.genpass - [`cryptography`]\n- web.request - [`requests`, `aiohttp`]\n- utils.compressor - [`brotli`, `zstandard`, `py7zr`]\n- io.gui - [`PySide6`]\n\nSub-Modules that may be removed in future updates due to being hard to support or simply unneeded.\n\n- database (maybe unneeded and hard to support if more dbs are added -> new_database is being developed)\n- loggers (maybe unneeded)\n\n## Contributing\n\nWe welcome contributions! Please see our [contributing guidelines](https://github.com/adalfarus/aplustools/blob/main/CONTRIBUTING.md) for more details on how you can contribute to aplustools.\n\n1. Fork the repository\n2. Create your feature branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)\n4. Push to the branch (`git push origin feature/AmazingFeature`)\n5. Open a pull request\n\n## License\n\naplustools is licensed under the GPL-3.0 License - see the [LICENSE](https://github.com/adalfarus/aplustools/blob/main/LICENSE) file for details.\n",
    "bugtrack_url": null,
    "license": "GPL-3.0-or-later",
    "summary": "A collection of helpful tools",
    "version": "1.4.8.5",
    "project_urls": {
        "Documentation": "https://github.com/adalfarus/aplustools/wiki",
        "Home": "https://pypi.org/project/aplustools/",
        "Issue tracker": "https://github.com/adalfarus/aplustools/issues",
        "Repository": "https://github.com/adalfarus/aplustools"
    },
    "split_keywords": [
        "general",
        " tools",
        " app tools",
        " beta",
        " apt"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "5c0de978c5deecf3888774e8e5e684e87fea4428dbc24ce5c68e4e240bee46ba",
                "md5": "df7e820178585141fe7d3e94424d5e8a",
                "sha256": "f0a13879dfc9b44c6f58398a694b81ac9011cdda52ebf706375572f56a75daec"
            },
            "downloads": -1,
            "filename": "aplustools-1.4.8.5-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "df7e820178585141fe7d3e94424d5e8a",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9",
            "size": 223745,
            "upload_time": "2024-05-12T15:41:44",
            "upload_time_iso_8601": "2024-05-12T15:41:44.088520Z",
            "url": "https://files.pythonhosted.org/packages/5c/0d/e978c5deecf3888774e8e5e684e87fea4428dbc24ce5c68e4e240bee46ba/aplustools-1.4.8.5-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "e1f788582df93cfb29be0a81019b08e8503f28ce8607898f457502b9b7974e4e",
                "md5": "7d0a4a6f14b792d00bf765e5ca3d9970",
                "sha256": "c02985809e46ccf6f592af80acf456b72e86f7aed981c5af6ee732ac5f020aa3"
            },
            "downloads": -1,
            "filename": "aplustools-1.4.8.5.tar.gz",
            "has_sig": false,
            "md5_digest": "7d0a4a6f14b792d00bf765e5ca3d9970",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9",
            "size": 212301,
            "upload_time": "2024-05-12T15:41:46",
            "upload_time_iso_8601": "2024-05-12T15:41:46.179622Z",
            "url": "https://files.pythonhosted.org/packages/e1/f7/88582df93cfb29be0a81019b08e8503f28ce8607898f457502b9b7974e4e/aplustools-1.4.8.5.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-05-12 15:41:46",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "adalfarus",
    "github_project": "aplustools",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "aplustools"
}
        
Elapsed time: 1.13718s