• Stars
    star
    734
  • Rank 61,320 (Top 2 %)
  • Language
    Go
  • License
    MIT License
  • Created almost 8 years ago
  • Updated almost 4 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Generate .proto files from Go source code.

proteus

GoDoc Build Status codecov License Go Report Card codebeat badge

Notice: This repository is abandoned, and no further updates will be done on the code base, nor issues/PRs will be answered or attended.

Proteus /proʊtiΙ™s/ is a tool to generate protocol buffers version 3 compatible .proto files from your Go structs, types and functions.

The motivation behind this library is to use Go as a source of truth for your models instead of the other way around and then generating Go code from a .proto file, which does not generate idiomatic code.

Proteus scans all the code in the selected packages and generates protobuf messages for every exported struct (and all the ones that are referenced in any other struct, even though they are not exported). The types that semantically are used as enumerations in Go are transformed into proper protobuf enumerations. All the exported functions and methods will be turned into protobuf RPC services.

We want to build proteus in a very extensible way, so every step of the generation can be hackable via plugins and everyone can adapt proteus to their needs without actually having to integrate functionality that does not play well with the core library. We are releasing the plugin feature after Go 1.8 is released, which includes the plugin package of the standard library.

For an overall overview of the code architecture take a look at the architecture documentation.

You can read more about the motivations behind building proteus in this blog post.

Install

go get -v gopkg.in/src-d/proteus.v1/...

Requirements

There are two requirements for the full process.

  • protoc binary installed on your path
  • go get -u github.com/gogo/protobuf/...

Usage

You can generate the proto files, the marshal/unmarshal and the rest of protobuf stuff for your Go types, the RPC client and server interface and the RPC server implementation for your packages. That is, the whole process.

proteus -f /path/to/protos/folder \
        -p my/go/package \
        -p my/other/go/package

You can generate proto files only using the command line tool provided with proteus.

proteus proto -f /path/to/output/folder \
        -p my/go/package \
        -p my/other/go/package
        --verbose

You can also only generate gRPC server implementations for your packages.

proteus rpc -p my/go/package \
        -p my/other/go/package

NOTE: Of course, if the defaults don't suit your needs, until proteus is extensible via plugins, you can hack together your own generator command using the provided components. Check out the godoc documentation of the package.

Generate protobuf messages

Proteus will generate protobuf messages with the structure of structs with the comment //proteus:generate. Obviously, the structs have to be exported in Go (first letter must be in upper case).

//proteus:generate
type Exported struct {
        Field string
}

type NotExported struct {
        Field string
}

Generated by requirement

Note that, even if the struct is not explicitly exported, if another struct has a field of that type, it will be generated as well.

//proteus:generate
type Preference struct {
        Name string
        Value string
        Options Options
}

type Options struct {
        Enabled bool
}

In that example, even if Options is not explicitly generated, it will be because it is required to generate Preference.

So far, this does not happen if the field is an enum. It is a known problem and we are working on fixing it. Until said fix lands, please, explicitly mark enums to be generated.

Struct embedding

You can embed structs as usual and they will be generated as if the struct had the fields of the embedded struct.

//proteus:generate
type User struct {
        Model
        Username string
}

type Model struct {
        ID int
        CreatedAt time.Time
}

This example will generate the following protobuf message.

message User {
        int32 id = 1;
        google.protobuf.Timestamp created_at = 2;
        string username = 3;
}

CAUTION: if you redefine a field, it will be ignored and the one from the embedded will be taken. Same thing happens if you embed several structs and they have repeated fields. This may change in the future, for now this is the intended behaviour and a warning is printed.

Ignore specific fields

You can ignore specific fields using the struct tag proteus:"-".

//proteus:generate
type Foo struct {
        Bar int
        Baz int `proteus:"-"`
}

This becomes:

message Foo {
        int32 bar = 1;
}

Generating enumerations

You can make a type declaration (not a struct type declaration) be exported as an enumeration, instead of just an alias with the comment //proteus:generate.

//proteus:generate
type Status int

const (
        Pending Status = iota
        Active
        Closed
)

This will generate:

enum Status {
        PENDING = 0;
        ACTIVE = 1;
        CLOSED = 2;
}

NOTE: protobuf enumerations require you to start the enumeration with 0 and do not have gaps between the numbers. So keep that in mind when setting the values of your consts.

For example, if you have the following code:

type PageSize int

const (
        Mobile PageSize = 320
        Tablet PageSize = 768
        Desktop PageSize = 1024
)

Instead of doing an enumeration, consider not exporting the type and instead it will be treated as an alias of int32 in protobuf, which is the default behaviour for not exported types.

Generate services

For every package, a single service is generated with all the methods or functions having //proteus:generate.

For example, if you have the following package:

package users

//proteus:generate
func GetUser(id uint64) (*User, error) {
        // impl
}

//proteus:generate
func (s *UserStore) UpdateUser(u *User) error {
        // impl
}

The following protobuf service would be generated:

message GetUserRequest {
        uint64 arg1 = 1;
}

message UserStore_UpdateUserResponse {
}

service UsersService {
        rpc GetUser(users.GetUserRequest) returns (users.User);
        rpc UserStore_UpdateUser(users.User) returns (users.UserStore_UpdateUserResponse);
}

Note that protobuf does not support input or output types that are not messages or empty input/output, so instead of returning nothing in UserStore_UpdateUser it returns a message with no fields, and instead of receiving an integer in GetUser, receives a message with only one integer field. The last error type is ignored.

Generate RPC server implementation

gogo/protobuf generates the interface you need to implement based on your .proto file. The problem with that is that you actually have to implement that and maintain it. Instead, you can just generate it automatically with proteus.

Consider the Go code of the previous section, we could generate the implementation of that service.

Something like this would be generated:

type usersServiceServer struct {
}

func NewUsersServiceServer() *usersServiceServer {
        return &usersServiceServer{}
}

func (s *userServiceServer) GetUser(ctx context.Context, in *GetUserRequest) (result *User, err error) {
        result = GetUser(in.Arg1)
        return
}

func (s *userServiceServer) UserStore_UpdateUser(ctx context.Context, in *User) (result *UserStore_UpdateUser, err error) {
        s.UserStore.UpdateUser(in)
        return
}

There are 3 interesting things in the generated code that, of course, would not work:

  • usersServiceServer is a generated empty struct.
  • NewUsersServiceServer is a generated constructor for usersServiceServer.
  • UserStore_UpdateUser uses the field UserStore of userServiceServer that, indeed, does not exist.

The server struct and its constructor are always generated empty but only if they don't exist already. That means that you can, and should, implement them yourself to make this code work.

For every method you are using, you are supposed to implement a receiver in the server type and initialize it however you want in the constructor. How would we fix this?

type userServiceServer struct {
        UserStore *UserStore
}

func NewUserServiceServer() *userServiceServer {
        return &userServiceServer{
                UserStore: NewUserStore(),
        }
}

Now if we generate the code again, the server struct and the constructor are implemented and the defaults will not be added again. Also, UserStore_UpdateUser would be able to find the field UserStore in userServiceServer and the code would work.

Not scanned types

What happens if you have a type in your struct that is not in the list of scanned packages? It is completely ignored. The only exception to this are time.Time and time.Duration, which are allowed by default even though you are not adding time package to the list.

In the future, this will be extensible via plugins.

Examples

You can find an example of a real use case on the example folder. For checking how the server and client works, see server.go and client.go. The orchestration of server and client is done in example_test.go. The example creates a server and a new client and tests the output.

Features to come

  • Extensible mapping and options via plugins (waiting for Go 1.8 release).

Known Limitations

The following is a list of known limitations and the current state of them.

  • Only {,u}int32 and {,u}int64 is supported in protobuf. Therefore, all {,u}int types are upgraded to the next size and a warning is printed. Same thing happens with floats and doubles.
  • If a struct contains a field of type time.Time, then that struct can only be serialized and deserialized using the Marshal and Unmarshal methods. Other marshallers use reflection and need a few struct tags generated by protobuf that your struct won't have. This also happens with fields whose type is a declaration to a slice of another type (type Alias []base).

Contribute

If you are interested on contributing to proteus, open an issue explaining which missing functionality you want to work in, and we will guide you through the implementation, and tell you beforehand if that is a functionality we might consider merging in the first place.

License

MIT, see LICENSE

More Repositories

1

awesome-machine-learning-on-source-code

Cool links & research papers related to Machine Learning applied to source code (MLonCode)
6,211
star
2

go-git

Project has been moved to: https://github.com/go-git/go-git
Go
4,908
star
3

hercules

Gaining advanced insights from Git repository history.
Go
2,201
star
4

gitbase

SQL interface to git repositories, written in Go. https://docs.sourced.tech/gitbase
Go
2,061
star
5

go-mysql-server

An extensible MySQL server implementation in Go.
Go
1,038
star
6

go-kallax

Kallax is a PostgreSQL typesafe ORM for the Go language.
Go
857
star
7

kmcuda

Large scale K-means and K-nn implementation on NVIDIA GPU / CUDA
Jupyter Notebook
788
star
8

wmd-relax

Calculates Word Mover's Distance Insanely Fast
Python
461
star
9

enry

A faster file programming language detector
Go
458
star
10

datasets

source{d} datasets ("big code") for source code analysis and machine learning on source code
Jupyter Notebook
320
star
11

guide

Aiming to be a fully transparent company. All information about source{d} and what it's like to work here.
JavaScript
293
star
12

lapjv

Linear Assignmment Problem solver using Jonker-Volgenant algorithm - Python 3 native module.
C++
247
star
13

go-license-detector

Reliable project licenses detector.
Go
235
star
14

engine-deprecated

[DISCONTINUED] Go to https://github.com/src-d/sourced-ce/
Go
217
star
15

go-billy

The missing interface filesystem abstraction for Go
Go
199
star
16

sourced-ce

source{d} Community Edition (CE)
Go
185
star
17

beanstool

Dependency free beanstalkd admin tool
Go
151
star
18

lookout

Assisted code review, running custom code analyzers on pull requests
Go
149
star
19

ml

sourced.ml is a library and command line tools to build and apply machine learning models on top of Universal Abstract Syntax Trees
Python
141
star
20

reading-club

Paper reading club at source{d}
115
star
21

minhashcuda

Weighted MinHash implementation on CUDA (multi-gpu).
C++
112
star
22

go-siva

siva - seekable indexed verifiable archiver
Go
97
star
23

jgit-spark-connector

jgit-spark-connector is a library for running scalable data retrieval pipelines that process any number of Git repositories for source code analysis.
Scala
71
star
24

gitbase-web

gitbase web client; source{d} CE comes with a new UI, check it at https://docs.sourced.tech/community-edition/
Go
57
star
25

gemini

Advanced similarity and duplicate source code at scale.
Scala
54
star
26

apollo

Advanced similarity and duplicate source code proof of concept for our research efforts.
Python
52
star
27

borges

borges collects and stores Git repositories.
Go
52
star
28

okrs

Objectives & Key Results repository for the source{d} team
48
star
29

vecino

Vecino is a command line application to discover Git repositories which are similar to the one that the user provides.
Python
46
star
30

go-queue

Queue is a generic interface to abstract the details of implementation of queue systems.
Go
46
star
31

jgscm

Jupyter support for Google Cloud Storage
Python
45
star
32

code2vec

MLonCode community effort to implement Learning Distributed Representations of Code (https://arxiv.org/pdf/1803.09473.pdf)
Python
40
star
33

coreos-nvidia

Yet another NVIDIA driver container for Container Linux (aka CoreOS)
Makefile
37
star
34

style-analyzer

Lookout Style Analyzer: fixing code formatting and typos during code reviews
Jupyter Notebook
32
star
35

code-annotation

🐈 Code Annotation Tool
JavaScript
28
star
36

flamingo

Flamingo is a very thin and simple platform-agnostic chat bot framework
Go
27
star
37

blog

source{d} blog
HTML
27
star
38

sparkpickle

Pure Python implementation of reading SequenceFile-s with pickles written by Spark's saveAsPickleFile()
Python
24
star
39

go-errors

Yet another errors package, implementing error handling primitives.
Go
23
star
40

infrastructure-dockerfiles

Dockerfile-s to build the images which power source{d}'s computing infrastructure.
Dockerfile
22
star
41

conferences

Tracking events, CfPs, abstracts, slides, and all other even related things
22
star
42

tmsc

Python
21
star
43

homebrew

Real homebrew!
21
star
44

models

Machine learning models for MLonCode trained using the source{d} stack
19
star
45

terraform-provider-online

Terraform provider for Online.net
Go
19
star
46

modelforge

Python library to share machine learning models easily and reliably.
Python
18
star
47

identity-matching

source{d} extension to match Git signatures to real people.
Go
17
star
48

tensorflow-swivel

C++
16
star
49

seriate

Optimal ordering of elements in a set given their distance matrix.
Python
16
star
50

gitcollector

Go
15
star
51

go-vitess

An automatic filter-branch of Go libraries from the great Vitess project.
Go
15
star
52

rovers

Rovers is a service to retrieve repository URLs from multiple repository hosting providers.
HTML
14
star
53

go-parse-utils

Go
14
star
54

ml-core

source{d} MLonCode foundation - core algorithms and models.
Python
14
star
55

charts

Applications for Kubernetes
Smarty
12
star
56

role2vec

TeX
12
star
57

snippet-ranger

Jupyter Notebook
12
star
58

fsbench

a small tool for benchmarking filesystems
Go
11
star
59

dev-similarity

Jupyter Notebook
11
star
60

go-log

Log is a generic logging library based on logrus
Go
11
star
61

tab-vs-spaces

Jupyter Notebook
10
star
62

ghsync

GitHub API v3 > PostgreSQL
Go
9
star
63

diffcuda

Accelerated bulk diff on GPU
C
9
star
64

ml-mining

Python
8
star
65

go-billy-siva

A limited go-billy filesystem implementation based on siva.
Go
8
star
66

go-compose-installer

A toolkit to create installers based on docker compose.
Go
8
star
67

github-reminder

A GitHub application to handle deadline reminders in a GitHub idiomatic way.
Go
8
star
68

go-git-fixtures

several git fixtures to run go-git tests
Go
8
star
69

docsrv

docsrv is an app to serve versioned documentation for GitHub projects on demand
Go
7
star
70

go-cli

CLI scaffolding for Go
Go
7
star
71

shell-complete

Python
7
star
72

kubernetes-local-pv-provisioner

Helping you setting up local persistent volumes
Go
7
star
73

engine-analyses

Analyses of open source projects with source{d} Engine
Jupyter Notebook
7
star
74

gypogit

[UNMAINTAINED] go-git wrapper for Python
Python
6
star
75

go-borges

Go
6
star
76

treediff

Python
6
star
77

engine-tour

Temporary storage for useful guides for the source{d} engine
Jupyter Notebook
6
star
78

jupyter-spark-docker

Dockerfile with jupyter and scala installed
Dockerfile
6
star
79

imports

Go
6
star
80

git-validate

Go
6
star
81

k8s-pod-headless-service-operator

Go
6
star
82

sourced-ui

source{d} UI
JavaScript
6
star
83

landing

landing for source{d}
HTML
5
star
84

lookout-terraform-analyzer

This is a lookout analyzer that checks if your PR has been Terraform fmt'ed when submitting it.
Go
5
star
85

swivel-spark-prep

Distributed equivalent of prep.py and fastprep from Swivel using Apache Spark.
Scala
5
star
86

ci

Make-based build system for Go projects at source{d}
Shell
5
star
87

framework

[DEPRECATED]
Go
4
star
88

platform-starter

Starter and basic configuration for platform frontend projects.
Go
4
star
89

metadata-retrieval

Go
4
star
90

lookout-sdk

SDK for lookout analyzers
Python
4
star
91

code-completion

autocompletion prototype
Python
4
star
92

siva-java

siva format implemented in Java
Java
4
star
93

design

All things design at source{d}: branding, guidelines, UI assets, media & co.
4
star
94

berserker

Large scale UAST extractor [DEPRECATED]
Shell
4
star
95

combustion

Go
3
star
96

tm-experiments

Topic Modeling Experiments on Source Code
Python
3
star
97

go-YouTokenToMe

Go
3
star
98

lookout-sdk-ml

SDK for ML based Lookout analyzers
Python
3
star
99

go-asdf

Advanced Scientific Data Format reader library in pure Go.
Go
3
star
100

google-cloud-dns-healthcheck

Go
3
star