Skip to content

Commit 109a1b0

Browse files
author
anton.myroniuk
committed
Add helloworld-proto package
0 parents  commit 109a1b0

File tree

6 files changed

+234
-0
lines changed

6 files changed

+234
-0
lines changed

.github/workflows/publish.yaml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: Upload package ty PYPI
2+
3+
on:
4+
release:
5+
types: [created]
6+
7+
jobs:
8+
publish:
9+
runs-on: ubuntu-latest
10+
timeout-minutes: 10
11+
environment: production
12+
13+
steps:
14+
- name: Check out repository code
15+
uses: actions/checkout@v3
16+
17+
- name: Set up Python
18+
uses: actions/setup-python@v4
19+
with:
20+
python-version: '3.10'
21+
22+
- name: Install dependencies
23+
run: |
24+
python -m pip install --upgrade pip
25+
pip install setuptools wheel twine
26+
pip install mypy-protobuf==3.6.0 grpcio==1.62.3 grpcio-tools==1.62.3
27+
28+
- name: Build and publish
29+
env:
30+
TWINE_USERNAME: '__token__'
31+
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
32+
run: |
33+
python setup.py bdist_wheel
34+
ls -lh dist/
35+
twine upload dist/*

.gitignore

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Created by .ignore support plugin (hsz.mobi)
2+
### Go template
3+
# Binaries for programs and plugins
4+
*.exe
5+
*.dll
6+
*.so
7+
*.dylib
8+
9+
.DS_Store
10+
11+
# Test binary, build with `go test -c`
12+
*.test
13+
14+
.tool-versions
15+
.idea/
16+
coverage.html
17+
18+
#ignore build artifacts
19+
bin/
20+
build/
21+
dist/
22+
*.egg-info
23+
python/*/
24+
__init__.py
25+
.eggs
26+
helloworld_proto/
27+
go/
28+
tmp/
29+
venv/

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# helloworld-proto
2+
3+
```bash
4+
pip install helloworld-proto==1.0.0
5+
```

api/helloworld/v1/helloworld.proto

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
syntax = "proto3";
2+
3+
package helloworld.v1;
4+
5+
service GreeterService {
6+
rpc SayHello (SayHelloRequest) returns (SayHelloResponse);
7+
}
8+
9+
message SayHelloRequest {
10+
string name = 1;
11+
}
12+
13+
message SayHelloResponse {
14+
string message = 1;
15+
}

requirements-dev.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
wheel
2+
grpcio==1.62.3
3+
grpcio-tools==1.62.3
4+
googleapis-common-protos==1.63.0
5+
setuptools-scm==6.0.1
6+
mypy-protobuf==3.6.0

setup.py

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
import os
2+
import re
3+
import fileinput
4+
import setuptools
5+
import subprocess
6+
from pathlib import Path
7+
8+
9+
package_dir = "helloworld_proto"
10+
11+
12+
def clean_build_directories():
13+
os.system("rm -rf *.egg-info")
14+
os.system("rm -rf dist")
15+
os.system("rm -rf build")
16+
os.system(f"rm -rf {package_dir}")
17+
18+
19+
def generate_python_classes_from_proto():
20+
protos_dir = "api"
21+
22+
os.system(f"mkdir {package_dir}")
23+
24+
python_out = f"./{package_dir}"
25+
python_grpc_out = f"./{package_dir}"
26+
inputs = f"./{protos_dir}"
27+
files = list(map(str, list(Path(f"./{protos_dir}").rglob("*.proto"))))
28+
files = remove_symlinks_to_protos(files) # protoc is failing on symlinks to already included protos
29+
30+
command = [
31+
"python3", "-m", "grpc_tools.protoc",
32+
f"-I {inputs}",
33+
f"--python_out={python_out}",
34+
f"--grpc_python_out={python_grpc_out}",
35+
f"--mypy_out={python_out}",
36+
f"--mypy_grpc_out={python_grpc_out}",
37+
"--experimental_allow_proto3_optional",
38+
*files
39+
]
40+
command = " ".join(command)
41+
42+
work_dir = os.getcwd()
43+
exit_code = subprocess.Popen(command, cwd=work_dir, shell=True).wait()
44+
if exit_code != 0:
45+
print("Protobuf generation failed, please check logs above")
46+
exit(exit_code)
47+
48+
49+
def remove_symlinks_to_protos(proto_files):
50+
clean_files = []
51+
52+
for proto_file in proto_files:
53+
real_path = os.path.realpath(proto_file)
54+
relative_real = os.path.relpath(real_path)
55+
56+
if os.path.islink(proto_file) and relative_real in proto_files:
57+
print(f"Excluding file {proto_file} because it is a symlink for {relative_real}")
58+
else:
59+
clean_files.append(proto_file)
60+
61+
return clean_files
62+
63+
64+
def insert_init_files():
65+
for root, dirs, files in os.walk(f"./{package_dir}"):
66+
init_file_path = os.path.join(os.path.abspath(root), "__init__.py")
67+
with open(init_file_path, "w"):
68+
pass
69+
70+
71+
def fix_imports():
72+
def rewrite_py_file(file_input):
73+
for line in file_input:
74+
match = re.search("(?<!google\.protobuf) import .*_pb2 as", line)
75+
76+
if match:
77+
line = line.replace("from ", f"from {package_dir}.")
78+
79+
print(line, end="")
80+
81+
def rewrite_pyi_file(file_input):
82+
for line in file_input:
83+
matches = {
84+
match for match in re.findall(r"[\w\.]*_pb2", line)
85+
if not match.startswith("google.protobuf")
86+
}
87+
for match in matches:
88+
line = line.replace(match, f"{package_dir}.{match}")
89+
90+
print(line, end="")
91+
92+
for root, dirs, files in os.walk(f"./{package_dir}"):
93+
for file_name in files:
94+
file_path = os.path.join(os.path.abspath(root), file_name)
95+
96+
with fileinput.input(file_path, inplace=True) as f:
97+
if file_name.endswith(".py"):
98+
rewrite_py_file(f)
99+
elif file_name.endswith(".pyi"):
100+
rewrite_pyi_file(f)
101+
102+
103+
def setup():
104+
required = ["googleapis-common-protos>=1.52.0"]
105+
106+
setuptools.setup(
107+
name="helloworld-proto",
108+
use_scm_version={
109+
"version_scheme": "post-release",
110+
"local_scheme": "no-local-version",
111+
"relative_to": __file__,
112+
},
113+
setup_requires=["wheel", "setuptools_scm"],
114+
author="Reface",
115+
description="Proto example package",
116+
url="https://github.com/RefaceAI/helloworld-proto",
117+
packages=setuptools.find_packages(),
118+
install_requires=required,
119+
classifiers=[
120+
"Programming Language :: Python",
121+
"Programming Language :: Python :: 3",
122+
"Programming Language :: Python :: 3.8",
123+
"Programming Language :: Python :: 3.9",
124+
"Programming Language :: Python :: 3.10",
125+
"Programming Language :: Python :: 3.11",
126+
"Programming Language :: Python :: 3.12",
127+
"Programming Language :: Python :: 3.13",
128+
],
129+
package_data={
130+
"": ["*.pyi"],
131+
},
132+
)
133+
134+
135+
def run():
136+
clean_build_directories()
137+
generate_python_classes_from_proto()
138+
fix_imports()
139+
insert_init_files()
140+
setup()
141+
142+
143+
if __name__ == "__main__":
144+
run()

0 commit comments

Comments
 (0)