Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pkg #1

Merged
merged 1 commit into from
Jan 8, 2025
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
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
liberapay: jarbasAI
25 changes: 25 additions & 0 deletions .github/workflows/build_tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Run Build Tests
on:
push:
workflow_dispatch:

jobs:
build_tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: ${{ github.head_ref }}
- name: Setup Python
uses: actions/setup-python@v1
with:
python-version: "3.11"
- name: Install Build Tools
run: |
python -m pip install build wheel
- name: Build Distribution Packages
run: |
python setup.py bdist_wheel
- name: Install package
run: |
pip install .
10 changes: 10 additions & 0 deletions .github/workflows/conventional-label.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# auto add labels to PRs
on:
pull_request_target:
types: [ opened, edited ]
name: conventional-release-labels
jobs:
label:
runs-on: ubuntu-latest
steps:
- uses: bcoe/conventional-release-labels@v1
58 changes: 58 additions & 0 deletions .github/workflows/publish_stable.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Stable Release
on:
push:
branches: [master]
workflow_dispatch:

jobs:
publish_stable:
uses: TigreGotico/gh-automations/.github/workflows/publish-stable.yml@master
secrets: inherit
with:
branch: 'master'
version_file: 'zbase/version.py'
setup_py: 'setup.py'
publish_release: true

publish_pypi:
needs: publish_stable
if: success() # Ensure this job only runs if the previous job succeeds
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: dev
fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository.
- name: Setup Python
uses: actions/setup-python@v1
with:
python-version: "3.11"
- name: Install Build Tools
run: |
python -m pip install build wheel
- name: version
run: echo "::set-output name=version::$(python setup.py --version)"
id: version
- name: Build Distribution Packages
run: |
python setup.py sdist bdist_wheel
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@master
with:
password: ${{secrets.PYPI_TOKEN}}


sync_dev:
needs: publish_stable
if: success() # Ensure this job only runs if the previous job succeeds
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository.
ref: master
- name: Push master -> dev
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: dev
108 changes: 108 additions & 0 deletions .github/workflows/release_workflow.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
name: Release Alpha and Propose Stable

on:
pull_request:
types: [closed]
branches: [dev]

jobs:
publish_alpha:
if: github.event.pull_request.merged == true
uses: TigreGotico/gh-automations/.github/workflows/publish-alpha.yml@master
secrets: inherit
with:
branch: 'dev'
version_file: 'zbase/version.py'
setup_py: 'setup.py'
update_changelog: true
publish_prerelease: true
changelog_max_issues: 100

notify:
if: github.event.pull_request.merged == true
needs: publish_alpha
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Send message to Matrix bots channel
id: matrix-chat-message
uses: fadenb/[email protected]
with:
homeserver: 'matrix.org'
token: ${{ secrets.MATRIX_TOKEN }}
channel: '!WjxEKjjINpyBRPFgxl:krbel.duckdns.org'
message: |
new ${{ github.event.repository.name }} PR merged! https://github.com/${{ github.repository }}/pull/${{ github.event.number }}

publish_pypi:
needs: publish_alpha
if: success() # Ensure this job only runs if the previous job succeeds
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: dev
fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository.
- name: Setup Python
uses: actions/setup-python@v1
with:
python-version: "3.11"
- name: Install Build Tools
run: |
python -m pip install build wheel
- name: version
run: echo "::set-output name=version::$(python setup.py --version)"
id: version
- name: Build Distribution Packages
run: |
python setup.py sdist bdist_wheel
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@master
with:
password: ${{secrets.PYPI_TOKEN}}


propose_release:
needs: publish_alpha
if: success() # Ensure this job only runs if the previous job succeeds
runs-on: ubuntu-latest
steps:
- name: Checkout dev branch
uses: actions/checkout@v3
with:
ref: dev

- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: "3.11"

- name: Get version from setup.py
id: get_version
run: |
VERSION=$(python setup.py --version)
echo "VERSION=$VERSION" >> $GITHUB_ENV

- name: Create and push new branch
run: |
git checkout -b release-${{ env.VERSION }}
git push origin release-${{ env.VERSION }}

- name: Open Pull Request from dev to master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Variables
BRANCH_NAME="release-${{ env.VERSION }}"
BASE_BRANCH="master"
HEAD_BRANCH="release-${{ env.VERSION }}"
PR_TITLE="Release ${{ env.VERSION }}"
PR_BODY="Human review requested!"

# Create a PR using GitHub API
curl -X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: token $GITHUB_TOKEN" \
-d "{\"title\":\"$PR_TITLE\",\"body\":\"$PR_BODY\",\"head\":\"$HEAD_BRANCH\",\"base\":\"$BASE_BRANCH\"}" \
https://api.github.com/repos/${{ github.repository }}/pulls

108 changes: 96 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,98 @@
# Zbase - Base91 and Z85 Encodings

This repository provides C and Python implementations of three encoding schemes: **Z85P**, **Base91**, and **Z85B**.

| Encoding | Avg Encoding Time (ns) | Avg Decoding Time (ns) | Avg Size Increase | Encoding Rank | Decoding Rank | Size Increase Rank |
|-------------|-------------------------|-------------------------|-------------------|---------------|---------------|--------------------|
| [pybase64](https://github.com/mayeut/pybase64) | 1131 ns | 2946 ns | 1.35x | 1 🥇 | 1 🥇 | 4 |
| **base91** | 622324 ns | 38632 ns | 1.23x | 5 | 4 | 1 🥇 |
| [base64](https://docs.python.org/3/library/base64.html) | 7113 ns | 7051 ns | 1.35x | 3 🥉 | 3 🥉 | 4 |
| [base16](https://docs.python.org/3/library/binascii.html) | 5953 ns | 5859 ns | 2.00x | 2 🥈 | 2 🥈 | 6 |
| **z85b** | 626214 ns | 871890 ns | 1.25x | 6 | 6 | 2 🥈 |
| **z85p** | 633825 ns | 775821 ns | 1.28x | 7 | 5 | 3 🥉 |
| [base32](https://docs.python.org/3/library/base64.html) | 503698 ns | 882194 ns | 1.62x | 4 | 7 | 5 |
| [z85p_py](https://github.com/JarbasHiveMind/hivemind-websocket-client/blob/dev/hivemind_bus_client/encodings/z85p.py) | 940859 ns | 1159043 ns | 1.28x | 8 | 8 | 3 🥉 |
| [z85b_py](https://github.com/JarbasHiveMind/hivemind-websocket-client/blob/dev/hivemind_bus_client/encodings/z85b.py) | 983796 ns | 1314734 ns | 1.25x | 9 | 9 | 2 🥈 |
| [base91_py](https://github.com/JarbasHiveMind/hivemind-websocket-client/blob/dev/hivemind_bus_client/encodings/b91.py) | 1414374 ns | 2080957 ns | 1.23x | 10 | 10 | 1 🥇 |
The C-based shared libraries are optimized for performance, while Python implementations provide a fallback when the C
libraries are not available.

The repository contains:

- **Base91 encoding**: A binary-to-text encoding scheme that uses 91 printable ASCII characters.
- **Z85B encoding**: A variant of Z85 used for efficient binary-to-text encoding.
- **Z85P encoding**: Another variant of Z85, with different padding scheme.

## Features

- **C-based implementation** for each encoding scheme for maximum performance.
- **Pure Python fallback** for environments where the C libraries are not available.
- Easy-to-use API for encoding and decoding with detailed error handling and logging.
- Cross-platform support (Linux, macOS, Windows) via system architecture detection.

## Benchmarks

| Encoding | Avg Encoding Time (ns) | Avg Decoding Time (ns) | Avg Size Increase | Encoding Rank | Decoding Rank | Size Increase Rank |
|------------------------------------------------------------------------------------------------------------------------|------------------------|------------------------|-------------------|---------------|---------------|--------------------|
| [pybase64](https://github.com/mayeut/pybase64) | 1131 ns | 2946 ns | 1.35x | 1 🥇 | 1 🥇 | 4 |
| **base91** | 622324 ns | 38632 ns | 1.23x | 5 | 4 | 1 🥇 |
| [base64](https://docs.python.org/3/library/base64.html) | 7113 ns | 7051 ns | 1.35x | 3 🥉 | 3 🥉 | 4 |
| [base16](https://docs.python.org/3/library/binascii.html) | 5953 ns | 5859 ns | 2.00x | 2 🥈 | 2 🥈 | 6 |
| **z85b** | 626214 ns | 871890 ns | 1.25x | 6 | 6 | 2 🥈 |
| **z85p** | 633825 ns | 775821 ns | 1.28x | 7 | 5 | 3 🥉 |
| [base32](https://docs.python.org/3/library/base64.html) | 503698 ns | 882194 ns | 1.62x | 4 | 7 | 5 |
| [z85p_py](https://github.com/JarbasHiveMind/hivemind-websocket-client/blob/dev/hivemind_bus_client/encodings/z85p.py) | 940859 ns | 1159043 ns | 1.28x | 8 | 8 | 3 🥉 |
| [z85b_py](https://github.com/JarbasHiveMind/hivemind-websocket-client/blob/dev/hivemind_bus_client/encodings/z85b.py) | 983796 ns | 1314734 ns | 1.25x | 9 | 9 | 2 🥈 |
| [base91_py](https://github.com/JarbasHiveMind/hivemind-websocket-client/blob/dev/hivemind_bus_client/encodings/b91.py) | 1414374 ns | 2080957 ns | 1.23x | 10 | 10 | 1 🥇 |

## Usage

You can use the provided classes to encode and decode data using the supported encoding schemes.

### Z85P Encoding

```python
from z85p import Z85P

# Encode data
data = b"Hello, World!"
encoded = Z85P.encode(data)
print("Encoded Z85P:", encoded)

# Decode data
decoded = Z85P.decode(encoded)
print("Decoded Z85P:", decoded)
```

### Base91 Encoding

```python
from base91 import B91

# Encode data
data = b"Hello, World!"
encoded = B91.encode(data)
print("Encoded Base91:", encoded)

# Decode data
decoded = B91.decode(encoded)
print("Decoded Base91:", decoded)
```

### Z85B Encoding

```python
from z85b import Z85B

# Encode data
data = b"Hello, World!"
encoded = Z85B.encode(data)
print("Encoded Z85B:", encoded)

# Decode data
decoded = Z85B.decode(encoded)
print("Decoded Z85B:", decoded)
```

## Error Handling

The library automatically falls back to the Python implementation if the C libraries are not found or fail to load. Any
issues related to encoding or decoding will raise a `ValueError` with a detailed message.

In the case of missing C libraries, warnings will be logged using Python's built-in `logging` module.

### Logging

The library uses the `logging` module to provide useful runtime information:

```bash
2025-01-08 12:34:56,789 - WARNING - Z85P C library not available: Library load error. Falling back to pure Python implementation.
```
50 changes: 50 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import os
from setuptools import setup

BASEDIR = os.path.abspath(os.path.dirname(__file__))


def get_version():
""" Find the version of the package"""
version_file = os.path.join(BASEDIR, 'zbase', 'version.py')
major, minor, build, alpha = (None, None, None, None)
with open(version_file) as f:
for line in f:
if 'VERSION_MAJOR' in line:
major = line.split('=')[1].strip()
elif 'VERSION_MINOR' in line:
minor = line.split('=')[1].strip()
elif 'VERSION_BUILD' in line:
build = line.split('=')[1].strip()
elif 'VERSION_ALPHA' in line:
alpha = line.split('=')[1].strip()

if ((major and minor and build and alpha) or
'# END_VERSION_BLOCK' in line):
break
version = f"{major}.{minor}.{build}"
if int(alpha):
version += f"a{alpha}"
return version


def required(requirements_file):
""" Read requirements file and remove comments and empty lines. """
with open(os.path.join(BASEDIR, requirements_file), 'r') as f:
requirements = f.read().splitlines()
return [pkg for pkg in requirements
if pkg.strip() and not pkg.startswith("#")]



setup(
name='zbase',
version=get_version(),
packages=['zbase'],
url='https://github.com/JarbasHiveMind/zbase',
license='Apache-2.0',
author='jarbasAi',
include_package_data=True,
author_email='[email protected]',
description='base91, z85b and z85p encodings'
)
Loading
Loading