Skip to content

Remove @dataclass, add slots #144

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

Closed
wants to merge 88 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
64da80a
First go at dataslots
Gobot1234 Aug 24, 2020
0d6ced5
Implement Message.__bool__ for #130
Gobot1234 Aug 24, 2020
7746b91
Add a test for it
Gobot1234 Aug 24, 2020
42cd924
Custom Metaclass that removes need for @dataclass
Gobot1234 Aug 27, 2020
955bbb3
Revert private attributes
Gobot1234 Aug 27, 2020
1597c48
Delete utils.py
Gobot1234 Aug 27, 2020
f81d8cd
Remove brackets
Gobot1234 Aug 27, 2020
1b66467
Cleanup
Gobot1234 Aug 27, 2020
5056997
See if this fixes stuff
Gobot1234 Aug 27, 2020
62de49c
Remove debug print
Gobot1234 Aug 27, 2020
397c6b0
Update template.py.j2
Gobot1234 Aug 27, 2020
16cdaa8
Some bugfixes/optimizations
Gobot1234 Aug 27, 2020
8353b24
Misc comments
Gobot1234 Aug 27, 2020
5373229
Fixes
Gobot1234 Aug 28, 2020
b08a036
Optimize init
Gobot1234 Aug 29, 2020
86a9726
Fix typing
Gobot1234 Aug 29, 2020
18a0ea0
More fixes
Gobot1234 Aug 29, 2020
f0fb3d1
Remove dataclass
Gobot1234 Aug 29, 2020
18d5ec9
Bug fixes
Gobot1234 Aug 29, 2020
13fc75d
Blacken
Gobot1234 Aug 29, 2020
1a07d3b
Couple of small tweaks
Gobot1234 Aug 29, 2020
adc7eba
Merge branch 'master' into dataslots
Gobot1234 Sep 1, 2020
3ff8213
Blacken + tweak
Gobot1234 Sep 1, 2020
2d757fc
Blacken again
Gobot1234 Sep 1, 2020
53a7df0
Merge branch 'master' into master
Gobot1234 Sep 2, 2020
9da923d
Blacken
Gobot1234 Sep 2, 2020
12ae52a
Fixes
Gobot1234 Sep 2, 2020
854325f
Fixes
Gobot1234 Sep 2, 2020
8d62106
Fix arg/kwarg handling
Gobot1234 Sep 2, 2020
90ac7a6
Fix recursive messages & blacken
Gobot1234 Sep 2, 2020
6461109
Final fix?
Gobot1234 Sep 2, 2020
6bc4a35
Final final fix
Gobot1234 Sep 2, 2020
1067b46
Respond to self comments
Gobot1234 Sep 3, 2020
6e21f64
More speed improvements and final changes
Gobot1234 Sep 7, 2020
17e31f4
Update tests
Gobot1234 Sep 19, 2020
a53d805
Fix bool
Gobot1234 Sep 19, 2020
b3b7c00
Fix failing tests
Gobot1234 Sep 19, 2020
a3f5f21
Add benchmarks (#148)
adriangb Sep 19, 2020
58556e0
Update README with example of calling protoc from python (#149)
spacecowboy Sep 19, 2020
d3e4fbb
Add Documentation (#125)
Gobot1234 Sep 20, 2020
4630c1c
bump grpclib to 0.4.1 (#150)
jck Sep 23, 2020
bf9412e
Use poetry-core as PEP 517 build backend (#108)
abn Oct 1, 2020
8f7af27
QOL fixes (#141)
Gobot1234 Oct 17, 2020
4a4429d
Update docs
Gobot1234 Oct 19, 2020
48e80cf
Merge branch 'master' into master
Gobot1234 Oct 19, 2020
99183bf
First go at dataslots
Gobot1234 Aug 24, 2020
a8fb99b
Custom Metaclass that removes need for @dataclass
Gobot1234 Aug 27, 2020
7d67deb
Revert private attributes
Gobot1234 Aug 27, 2020
eab6124
Delete utils.py
Gobot1234 Aug 27, 2020
a179f9b
Remove brackets
Gobot1234 Aug 27, 2020
4ecfd5b
Cleanup
Gobot1234 Aug 27, 2020
7e4ab04
See if this fixes stuff
Gobot1234 Aug 27, 2020
d4f8330
Remove debug print
Gobot1234 Aug 27, 2020
b6be561
Update template.py.j2
Gobot1234 Aug 27, 2020
da8d705
Some bugfixes/optimizations
Gobot1234 Aug 27, 2020
c0771e1
Misc comments
Gobot1234 Aug 27, 2020
9891960
Fixes
Gobot1234 Aug 28, 2020
cc71df2
Optimize init
Gobot1234 Aug 29, 2020
030756f
Fix typing
Gobot1234 Aug 29, 2020
75b927d
More fixes
Gobot1234 Aug 29, 2020
565531a
Remove dataclass
Gobot1234 Aug 29, 2020
a22030c
Bug fixes
Gobot1234 Aug 29, 2020
9f0b5bf
Blacken
Gobot1234 Aug 29, 2020
c7159ea
Couple of small tweaks
Gobot1234 Aug 29, 2020
29c3ad9
Blacken + tweak
Gobot1234 Sep 1, 2020
8b35c1e
Blacken again
Gobot1234 Sep 1, 2020
bdc1f46
Fixes
Gobot1234 Sep 2, 2020
23728fe
Fixes
Gobot1234 Sep 2, 2020
4e99449
Fix arg/kwarg handling
Gobot1234 Sep 2, 2020
008c0d3
Fix recursive messages & blacken
Gobot1234 Sep 2, 2020
6f74c5d
Final fix?
Gobot1234 Sep 2, 2020
8ed2805
Final final fix
Gobot1234 Sep 2, 2020
35c4ee4
Respond to self comments
Gobot1234 Sep 3, 2020
68ae143
More speed improvements and final changes
Gobot1234 Sep 7, 2020
86d7c30
Add __bool__ to special members
Gobot1234 Oct 20, 2020
a304628
Respond to some of the comments
Gobot1234 Oct 20, 2020
14748ae
Merge remote-tracking branch 'origin/dataslots' into dataslots
Gobot1234 Oct 20, 2020
5c8e926
Update __init__.py
Gobot1234 Oct 20, 2020
fec636a
Hmm
Gobot1234 Oct 25, 2020
31579f6
Fix broken branch
Gobot1234 Oct 25, 2020
f10bec4
Simplify bool
Gobot1234 Oct 27, 2020
f48080b
Fix broken branch P2 but with changes and a better structure
Gobot1234 Nov 7, 2020
5e005d3
Fix function
Gobot1234 Nov 7, 2020
ff712f7
Update stuff for slack in case anyone looks
Gobot1234 Nov 7, 2020
529c488
Whoops
Gobot1234 Nov 7, 2020
50949b5
Merge branch 'master' into dataslots
Gobot1234 Nov 7, 2020
3d0fca6
Fix tests and benchmarks
Gobot1234 Nov 7, 2020
222a105
Fix tests
Gobot1234 Nov 7, 2020
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
File renamed without changes.
12 changes: 9 additions & 3 deletions .github/workflows/code-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,18 @@ on:
- '**'

jobs:
black:
name: Black
check-formatting:
name: Check code/doc formatting
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run Black
uses: lgeiger/black-action@master
with:
args: --check src/ tests/
args: --check src/ tests/ benchmarks/

- name: Install rST dependcies
run: python -m pip install doc8
- name: Lint documentation for errors
run: python -m doc8 docs --max-line-length 88 --ignore-path-errors "docs/migrating.rst;D001"
# it has a table which is longer than 88 characters long
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ output
.DS_Store
.tox
.venv
.asv
venv
17 changes: 17 additions & 0 deletions .readthedocs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
version: 2
formats: []

build:
image: latest

sphinx:
configuration: docs/conf.py
fail_on_warning: false

python:
version: 3.7
install:
- method: pip
path: .
extra_requirements:
- dev
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,20 @@ message Greeting {
}
```

You can run the following:
You can run the following to invoke protoc directly:

```sh
mkdir lib
protoc -I . --python_betterproto_out=lib example.proto
```

or run the following to invoke protoc via grpcio-tools:

```sh
pip install grpcio-tools
python -m grpc_tools.protoc -I . --python_betterproto_out=lib example.proto
```

This will generate `lib/hello/__init__.py` which looks like:

```python
Expand Down Expand Up @@ -319,7 +326,7 @@ datetime.datetime(2019, 1, 1, 11, 59, 58, 800000, tzinfo=datetime.timezone.utc)
## Development

- _Join us on [Slack](https://join.slack.com/t/betterproto/shared_invite/zt-f0n0uolx-iN8gBNrkPxtKHTLpG3o1OQ)!_
- _See how you can help → [Contributing](CONTRIBUTING.md)_
- _See how you can help → [Contributing](.github/CONTRIBUTING.md)_

### Requirements

Expand Down
157 changes: 157 additions & 0 deletions asv.conf.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
{
// The version of the config file format. Do not change, unless
// you know what you are doing.
"version": 1,

// The name of the project being benchmarked
"project": "python-betterproto",

// The project's homepage
"project_url": "https://github.com/danielgtaylor/python-betterproto",

// The URL or local path of the source code repository for the
// project being benchmarked
"repo": ".",

// The Python project's subdirectory in your repo. If missing or
// the empty string, the project is assumed to be located at the root
// of the repository.
// "repo_subdir": "",

// Customizable commands for building, installing, and
// uninstalling the project. See asv.conf.json documentation.
//
"install_command": ["python -m pip install ."],
"uninstall_command": ["return-code=any python -m pip uninstall -y {project}"],
"build_command": ["python -m pip wheel -w {build_cache_dir} {build_dir}"],

// List of branches to benchmark. If not provided, defaults to "master"
// (for git) or "default" (for mercurial).
// "branches": ["master"], // for git
// "branches": ["default"], // for mercurial

// The DVCS being used. If not set, it will be automatically
// determined from "repo" by looking at the protocol in the URL
// (if remote), or by looking for special directories, such as
// ".git" (if local).
// "dvcs": "git",

// The tool to use to create environments. May be "conda",
// "virtualenv" or other value depending on the plugins in use.
// If missing or the empty string, the tool will be automatically
// determined by looking for tools on the PATH environment
// variable.
"environment_type": "virtualenv",

// timeout in seconds for installing any dependencies in environment
// defaults to 10 min
//"install_timeout": 600,

// the base URL to show a commit for the project.
// "show_commit_url": "http://github.com/owner/project/commit/",

// The Pythons you'd like to test against. If not provided, defaults
// to the current version of Python used to run `asv`.
// "pythons": ["2.7", "3.6"],

// The list of conda channel names to be searched for benchmark
// dependency packages in the specified order
// "conda_channels": ["conda-forge", "defaults"],

// The matrix of dependencies to test. Each key is the name of a
// package (in PyPI) and the values are version numbers. An empty
// list or empty string indicates to just test against the default
// (latest) version. null indicates that the package is to not be
// installed. If the package to be tested is only available from
// PyPi, and the 'environment_type' is conda, then you can preface
// the package name by 'pip+', and the package will be installed via
// pip (with all the conda available packages installed first,
// followed by the pip installed packages).
//
// "matrix": {
// "numpy": ["1.6", "1.7"],
// "six": ["", null], // test with and without six installed
// "pip+emcee": [""], // emcee is only available for install with pip.
// },

// Combinations of libraries/python versions can be excluded/included
// from the set to test. Each entry is a dictionary containing additional
// key-value pairs to include/exclude.
//
// An exclude entry excludes entries where all values match. The
// values are regexps that should match the whole string.
//
// An include entry adds an environment. Only the packages listed
// are installed. The 'python' key is required. The exclude rules
// do not apply to includes.
//
// In addition to package names, the following keys are available:
//
// - python
// Python version, as in the *pythons* variable above.
// - environment_type
// Environment type, as above.
// - sys_platform
// Platform, as in sys.platform. Possible values for the common
// cases: 'linux2', 'win32', 'cygwin', 'darwin'.
//
// "exclude": [
// {"python": "3.2", "sys_platform": "win32"}, // skip py3.2 on windows
// {"environment_type": "conda", "six": null}, // don't run without six on conda
// ],
//
// "include": [
// // additional env for python2.7
// {"python": "2.7", "numpy": "1.8"},
// // additional env if run on windows+conda
// {"platform": "win32", "environment_type": "conda", "python": "2.7", "libpython": ""},
// ],

// The directory (relative to the current directory) that benchmarks are
// stored in. If not provided, defaults to "benchmarks"
// "benchmark_dir": "benchmarks",

// The directory (relative to the current directory) to cache the Python
// environments in. If not provided, defaults to "env"
"env_dir": ".asv/env",

// The directory (relative to the current directory) that raw benchmark
// results are stored in. If not provided, defaults to "results".
"results_dir": ".asv/results",

// The directory (relative to the current directory) that the html tree
// should be written to. If not provided, defaults to "html".
"html_dir": ".asv/html",

// The number of characters to retain in the commit hashes.
// "hash_length": 8,

// `asv` will cache results of the recent builds in each
// environment, making them faster to install next time. This is
// the number of builds to keep, per environment.
// "build_cache_size": 2,

// The commits after which the regression search in `asv publish`
// should start looking for regressions. Dictionary whose keys are
// regexps matching to benchmark names, and values corresponding to
// the commit (exclusive) after which to start looking for
// regressions. The default is to start from the first commit
// with results. If the commit is `null`, regression detection is
// skipped for the matching benchmark.
//
// "regressions_first_commits": {
// "some_benchmark": "352cdf", // Consider regressions only after this commit
// "another_benchmark": null, // Skip regression detection altogether
// },

// The thresholds for relative change in results, after which `asv
// publish` starts reporting regressions. Dictionary of the same
// form as in ``regressions_first_commits``, with values
// indicating the thresholds. If multiple entries match, the
// maximum is taken. If no entry matches, the default is 5%.
//
// "regressions_thresholds": {
// "some_benchmark": 0.01, // Threshold of 1%
// "another_benchmark": 0.5, // Threshold of 50%
// },
}
1 change: 1 addition & 0 deletions benchmarks/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

56 changes: 56 additions & 0 deletions benchmarks/benchmarks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import betterproto


class TestMessage(betterproto.Message):
foo: int = betterproto.uint32_field(0)
bar: str = betterproto.string_field(1)
baz: float = betterproto.float_field(2)


class BenchMessage:
"""Test creation and usage a proto message."""

def setup(self):
self.cls = TestMessage
self.instance = TestMessage()
self.instance_filled = TestMessage(0, "test", 0.0)

def time_overhead(self):
"""Overhead in class definition."""

class Message(betterproto.Message):
foo: int = betterproto.uint32_field(0)
bar: str = betterproto.string_field(1)
baz: float = betterproto.float_field(2)

def time_instantiation(self):
"""Time instantiation"""
self.cls()

def time_attribute_access(self):
"""Time to access an attribute"""
self.instance.foo
self.instance.bar
self.instance.baz

def time_init_with_values(self):
"""Time to set an attribute"""
self.cls(0, "test", 0.0)

def time_attribute_setting(self):
"""Time to set attributes"""
self.instance.foo = 0
self.instance.bar = "test"
self.instance.baz = 0.0

def time_serialize(self):
"""Time serializing a message to wire."""
bytes(self.instance_filled)


class MemSuite:
def setup(self):
self.cls = TestMessage

def mem_instance(self):
return self.cls()
31 changes: 31 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
.. currentmodule:: betterproto

API reference
=============

The following document outlines betterproto's api. **None** of these classes should be
extended by the user manually.


Message
--------

.. autoclass:: betterproto.Message
:members:
:special-members: __bytes__, __bool__


.. autofunction:: betterproto.serialized_on_wire

.. autofunction:: betterproto.which_one_of


Enumerations
-------------

.. autoclass:: betterproto.Enum()
:members:


.. autoclass:: betterproto.Casing()
:members:
60 changes: 60 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.

import pathlib

import toml


# -- Project information -----------------------------------------------------

project = "betterproto"
copyright = "2019 Daniel G. Taylor"
author = "danielgtaylor"
pyproject = toml.load(open(pathlib.Path(__file__).parent.parent / "pyproject.toml"))


# The full version, including alpha/beta/rc tags.
release = pyproject["tool"]["poetry"]["version"]


# -- General configuration ---------------------------------------------------

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.intersphinx",
"sphinx.ext.napoleon",
]

autodoc_member_order = "bysource"
autodoc_typehints = "none"

extlinks = {
"issue": ("https://github.com/danielgtaylor/python-betterproto/issues/%s", "GH-"),
}

# Links used for cross-referencing stuff in other documentation
intersphinx_mapping = {
"py": ("https://docs.python.org/3", None),
}


# -- Options for HTML output -------------------------------------------------

# The name of the Pygments (syntax highlighting) style to use.
pygments_style = "friendly"

# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.

html_theme = "sphinx_rtd_theme"
Loading