Skip to content

Commit

Permalink
Modernize project infrastructure
Browse files Browse the repository at this point in the history
- Add publish github action
- Add lint autoupdate github action
- Updated pre-commit-config
- Changed readme from RST to MD
- Changed setup.py/setup.cfg to pyproject.toml
- Write requirements in separate file.
  • Loading branch information
hgrecco committed Dec 3, 2023
1 parent a9e107f commit ac404de
Show file tree
Hide file tree
Showing 14 changed files with 310 additions and 261 deletions.
59 changes: 26 additions & 33 deletions .github/workflows/ci.yml
@@ -1,55 +1,37 @@
name: CI

on: [push, pull_request]
on: [push]

jobs:
test-linux:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.6, 3.7, 3.8, 3.9, '3.10']
extras: [true, false]

runs-on: ubuntu-latest
python-version: ["3.9", "3.10", "3.11", "3.12"]

env:
TEST_OPTS: "-rfsxEX -s --cov=serialize --cov-config=.coveragerc"
TEST_OPTS: "-rfsxEX -s --cov=. --cov-config=.coveragerc"

steps:
- uses: actions/checkout@v2
with:
fetch-depth: 100

- name: Get tags
run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
- uses: actions/checkout@v3

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'

- name: Get pip cache dir
id: pip-cache
run: echo "::set-output name=dir::$(pip cache dir)"
- name: Upgrade pip
run: python -m pip install --upgrade pip

- name: Setup caching
uses: actions/cache@v2
with:
path: ${{ steps.pip-cache.outputs.dir }}
key: pip-${{ matrix.python-version }}
restore-keys: |
pip-${{ matrix.python-version }}
- name: Install coverage
run: pip install pytest-cov

- name: Install dependencies
run: |
pip install .[test]
- name: Install package
run: python -m pip install .[test]

- name: Install extras
if: ${{ matrix.extras != false }}
run: pip install -r supported_pkgs.txt

- name: Run Tests
run: |
pytest $TEST_OPTS
- name: Test with pytest
run: pytest $TEST_OPTS

- name: Coverage report
run: coverage report -m
Expand All @@ -72,9 +54,20 @@ jobs:
with:
python-version: 3.x
- name: Coveralls Finished
continue-on-error: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COVERALLS_SERVICE_NAME: github
run: |
pip install coveralls
coveralls --finish
# Dummy task to summarize all. See https://github.com/bors-ng/bors-ng/issues/1300
ci-success:
name: ci
if: ${{ success() }}
needs: test-linux
runs-on: ubuntu-latest
steps:
- name: CI succeeded
run: exit 0
46 changes: 46 additions & 0 deletions .github/workflows/lint-autoupdate.yml
@@ -0,0 +1,46 @@
name: pre-commit

on:
schedule:
- cron: "0 0 * * 0" # every Sunday at 00:00 UTC
workflow_dispatch:


jobs:
autoupdate:
name: autoupdate
runs-on: ubuntu-latest
if: github.repository == 'hgrecco/serialize'
steps:
- name: checkout
uses: actions/checkout@v2
- name: Cache pip and pre-commit
uses: actions/cache@v2
with:
path: |
~/.cache/pre-commit
~/.cache/pip
key: ${{ runner.os }}-pre-commit-autoupdate
- name: setup python
uses: actions/setup-python@v2
with:
python-version: 3.x
- name: upgrade pip
run: python -m pip install --upgrade pip
- name: install dependencies
run: python -m pip install --upgrade pre-commit
- name: version info
run: python -m pip list
- name: autoupdate
uses: technote-space/create-pr-action@bfd4392c80dbeb54e0bacbcf4750540aecae6ed4
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
EXECUTE_COMMANDS: |
python -m pre_commit autoupdate
python -m pre_commit run --all-files
COMMIT_MESSAGE: 'pre-commit: autoupdate hook versions'
COMMIT_NAME: 'github-actions[bot]'
COMMIT_EMAIL: 'github-actions[bot]@users.noreply.github.com'
PR_TITLE: 'pre-commit: autoupdate hook versions'
PR_BRANCH_PREFIX: 'pre-commit/'
PR_BRANCH_NAME: 'autoupdate-${PR_ID}'
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Expand Up @@ -14,4 +14,4 @@ jobs:
- name: Lint
uses: pre-commit/action@v2.0.0
with:
extra_args: --all-files --show-diff-on-failure
extra_args: --all-files --show-diff-on-failure
27 changes: 27 additions & 0 deletions .github/workflows/publish.yml
@@ -0,0 +1,27 @@
name: Build and publish to PyPI

on:
push:
tags:
- '*'

jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- uses: actions/setup-python@v4
with:
python-version: '3.x'

- name: Install dependencies
run: python -m pip install build

- name: Build package
run: python -m build

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_API_TOKEN }}
30 changes: 21 additions & 9 deletions .pre-commit-config.yaml
@@ -1,13 +1,25 @@
repos:
- repo: https://github.com/psf/black
rev: 21.12b0
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: black
- repo: https://github.com/pycqa/isort
rev: 5.10.1
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.1.5
hooks:
- id: isort
- repo: https://gitlab.com/pycqa/flake8
rev: 3.9.2
- id: ruff
args: ["--fix"]
- id: ruff-format
- repo: https://github.com/executablebooks/mdformat
rev: 0.7.16
hooks:
- id: flake8
- id: mdformat
additional_dependencies:
- mdformat-gfm # GitHub-flavored Markdown
- mdformat-black
- repo: https://github.com/kynan/nbstripout
rev: 0.6.1
hooks:
- id: nbstripout
args: [--extra-keys=metadata.kernelspec metadata.language_info.version]
126 changes: 126 additions & 0 deletions README.md
@@ -0,0 +1,126 @@
[![Latest Version](https://img.shields.io/pypi/v/serialize.svg)](https://pypi.python.org/pypi/serialize)

[![License](https://img.shields.io/pypi/l/serialize.svg)](https://pypi.python.org/pypi/serialize)

[![Python Versions](https://img.shields.io/pypi/pyversions/serialize.svg)](https://pypi.python.org/pypi/serialize)

[![CI](https://github.com/hgrecco/serialize/workflows/CI/badge.svg)](https://github.com/hgrecco/serialize/actions?query=workflow%3ACI)

[![LINTER](https://github.com/hgrecco/serialize/workflows/Lint/badge.svg)](https://github.com/hgrecco/serialize/actions?query=workflow%3ALint)

[![Coverage](https://coveralls.io/repos/github/hgrecco/serialize/badge.svg?branch=master)](https://coveralls.io/github/hgrecco/serialize?branch=master)

# Serialize: A common Python API for multiple serialization formats

```
There are multiple serialization formats out there ...
... and great packages to use them.
```

But they all have a different API and switching among them is not so
simple as it should be. Serialize helps you to do it, including dealing
with custom classes. Let's dump a dict using the
<span class="title-ref">pickle</span> format:

```python
>>> from serialize import dumps, loads
>>> dumps(dict(answer=42), fmt='pickle')
b'\x80\x03}q\x00X\x06\x00\x00\x00answerq\x01K*s.'
>>> loads(_, fmt='pickle')
{'answer': 42}
```

And here comes the cool thing, you can just change the serialization
format without having to learn a new API. Let's now dump it using
msgpack:

```python
>>> dumps(dict(answer=42), fmt='msgpack')
b'\x81\xa6answer*'
>>> loads(_, fmt='msgpack')
{'answer': 42}
```

Serialize currently support 8 different formats:
<span class="title-ref">bson</span>,
<span class="title-ref">dill</span>, <span class="title-ref">json</span>
(builtin or with simplejson package),
<span class="title-ref">msgpack</span>,
<span class="title-ref">phpserialize</span>,
<span class="title-ref">pickle</span>,
<span class="title-ref">serpent</span> and
<span class="title-ref">yaml</span>. Serialize does not implement these
formats but rather relies on established, well tested packages. If they
are installed, serialize will use them.

```
** Serialize allows you to use them all with the same API! **
```

You can also use the <span class="title-ref">dump</span> and
<span class="title-ref">load</span> to write directly to file-like
object:

```python
>>> from serialize import dump, load
>>> with open('output.yaml', 'wb') as fp:
... dump(dict(answer=42), fp, fmt='yaml')
>>> with open('output.yaml', 'rb') as fp:
... load(fp, fmt='yaml')
{'answer': 42}
```

or use directly the filename and the format will be inferred:

```python
>>> dump(dict(answer=42), 'output.yaml')
>>> load('output.yaml')
{'answer': 42}
```

A very common case is to dump and load objects from custom classes such
as:

```python
>>> class User:
... def __init__(self, name, age):
... self.name = name
... self.age = age
...
>>> john = User('John Smith', 27)
```

But some serialization packages do not support this important feature
and the rest usually have very different API between them. Serialize
provides you a common, simple interface for this. You just need to
define a function that is able to convert the object to an instance of a
builtin type and the converse:

```python
>>> from serialize import register_class
>>> def user_to_builtin(u):
... return (u.name, u.age)
...
>>> def user_from_builtin(c):
... return User(c[0], c[1])
...

>>> register_class(User, user_to_builtin, user_from_builtin)
```

And that's all. You can then use it directly without any hassle:

```python
>>> dumps(john, fmt='bson')
b"y\x00\x00\x00\x03__bson_follow__\x00c\x00\x00\x00\x04__dumped_obj__
\x00\x1e\x00\x00\x00\x020\x00\x0b\x00\x00\x00John Smith\x00\x101\x00
\x1b\x00\x00\x00\x00\x02__class_name__\x00\x1c\x00\x00\x00<class '__m
ain__.Username'>\x00\x00\x00"
>>> v = loads(_, fmt='bson')
>>> v.name
'John Smith'
>>> v.age
27
```

Enjoy!

0 comments on commit ac404de

Please sign in to comment.