Skip to content

Commit 13c47f3

Browse files
committed
Check in an initial version of the pip rules.
This is broken off of my prototype repository, and there are a handful of TODOs left to resolve.
1 parent 9160fc7 commit 13c47f3

15 files changed

+592
-4
lines changed

.gitignore

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Compiled Object files
2+
*.slo
3+
*.lo
4+
*.o
5+
*.obj
6+
7+
# Precompiled Headers
8+
*.gch
9+
*.pch
10+
11+
# Compiled Dynamic libraries
12+
*.so
13+
*.dylib
14+
*.dll
15+
16+
# Fortran module files
17+
*.mod
18+
*.smod
19+
20+
# Compiled Static libraries
21+
*.lai
22+
*.la
23+
*.a
24+
*.lib
25+
26+
# Executables
27+
*.exe
28+
*.out
29+
*.app
30+
31+
# Emacs garbage
32+
*~
33+
34+
# Bazel directories
35+
bazel-*
36+
bazel-bin
37+
bazel-genfiles
38+
bazel-out
39+
bazel-testlogs

.travis.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
sudo: required
2+
dist: trusty
3+
language:
4+
- java
5+
jdk:
6+
- oraclejdk8 # Building Bazel requires JDK8.
7+
addons:
8+
apt:
9+
sources:
10+
- sourceline: 'deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8'
11+
key_url: 'https://storage.googleapis.com/bazel-apt/doc/apt-key.pub.gpg'
12+
packages:
13+
- bazel
14+
15+
install:
16+
- go get -u github.com/bazelbuild/buildifier/buildifier
17+
18+
script:
19+
# Check that all of our tools and samples build
20+
- bazel clean && bazel build //...
21+
# Check that all of our tests pass
22+
- bazel clean && bazel test //...
23+
24+
# Check for issues with the format of our bazel config files.
25+
- buildifier -mode=check $(find . -name BUILD -type f)
26+
- buildifier -mode=check $(find . -name WORKSPACE -type f)
27+
- buildifier -mode=check $(find . -name '*.bzl' -type f)

README.md

Lines changed: 101 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,17 @@
44

55
## Rules
66

7+
* [pip_import](#pip_import)
78
* [py_library](#py_library)
89
* [py_binary](#py_binary)
10+
* [py_test](#py_test)
911

1012
## Overview
1113

12-
This is a placeholder repository that provides aliases for the native Bazel
13-
python rules. In the future, this will also become the home for rules that
14-
download `pip` packages, and other non-Core Python functionality.
14+
This repository provides Python rules for Bazel. Currently, support for
15+
rules that are available from Bazel core are simple aliases to that bundled
16+
functionality. On top of that, this repository provides support for installing
17+
dependencies typically managed via `pip`.
1518

1619
## Setup
1720

@@ -23,14 +26,19 @@ git_repository(
2326
remote = "https://github.com/bazelbuild/rules_python.git",
2427
commit = "{HEAD}",
2528
)
29+
30+
# Only needed for PIP support:
31+
load("//python:pip.bzl", "pip_repositories")
32+
33+
pip_repositories()
2634
```
2735

2836
Then in your `BUILD` files load the python rules with:
2937

3038
``` python
3139
load(
3240
"@io_bazel_rules_python//python:python.bzl",
33-
"py_binary", "py_library"
41+
"py_binary", "py_library", "py_test",
3442
)
3543

3644
py_binary(
@@ -39,6 +47,51 @@ py_binary(
3947
)
4048
```
4149

50+
## Importing `pip` dependencies
51+
52+
These rules are designed to have developers continue using `requirements.txt`
53+
to express their dependencies in a Python idiomatic manner. These dependencies
54+
are imported into the Bazel dependency graph via a two-phased process in
55+
`WORKSPACE`:
56+
57+
```python
58+
load("@io_bazel_rules_python//python:pip.bzl", "pip_import")
59+
60+
# This rule translates the specified requirements.txt into
61+
# @my_deps//:requirements.bzl, which itself exposes a pip_install method.
62+
pip_import(
63+
name = "my_deps",
64+
requirements = "//path/to:requirements.txt",
65+
)
66+
67+
# Load the pip_install symbol for my_deps, and create the dependencies'
68+
# repositories.
69+
load("@my_deps//:requirements.txt", "pip_install")
70+
pip_install()
71+
```
72+
73+
## Consuming `pip` dependencies
74+
75+
Once a set of dependencies has been imported via `pip_import` and `pip_install`
76+
we can start consuming them in our `py_{binary,library,test}` rules. In support
77+
of this, the generated `requirements.bzl` also contains a `packages` method,
78+
which can be used directly in `deps=[]` to reference an imported `py_library`.
79+
80+
```python
81+
load("@my_deps//:requirements.txt", "packages")
82+
83+
py_library(
84+
name = "mylib",
85+
srcs = ["mylib.py"],
86+
deps = [
87+
":myotherlib",
88+
# This takes the name as specified in requirements.txt
89+
packages("importeddep"),
90+
]
91+
)
92+
```
93+
94+
4295
<a name="py_library"></a>
4396
## py_library
4497

@@ -48,3 +101,47 @@ See Bazel core [documentation](https://docs.bazel.build/versions/master/be/pytho
48101
## py_binary
49102

50103
See Bazel core [documentation](https://docs.bazel.build/versions/master/be/python.html#py_binary).
104+
105+
<a name="py_test"></a>
106+
## py_test
107+
108+
See Bazel core [documentation](https://docs.bazel.build/versions/master/be/python.html#py_test).
109+
110+
<a name="pip_import"></a>
111+
## pip_import
112+
113+
```python
114+
pip_import(name, requirements)
115+
```
116+
117+
A repository rule that imports a `requirements.txt` file and generates
118+
`requirements.bzl`.
119+
120+
<table class="table table-condensed table-bordered table-params">
121+
<colgroup>
122+
<col class="col-param" />
123+
<col class="param-description" />
124+
</colgroup>
125+
<thead>
126+
<tr>
127+
<th colspan="2">Attributes</th>
128+
</tr>
129+
</thead>
130+
<tbody>
131+
<tr>
132+
<td><code>name</code></td>
133+
<td>
134+
<p><code>Name, required</code></p>
135+
<p>Unique name for this repository rule.</p>
136+
</td>
137+
</tr>
138+
<tr>
139+
<td><code>requirements</code></td>
140+
<td>
141+
<p><code>A requirements.txt file; required</code></p>
142+
<p>This takes the path to a the <code>requirements.txt</code> file that
143+
expresses the Python library dependencies in an idiomatic manner.</p>
144+
</td>
145+
</tr>
146+
</tbody>
147+
</table>

WORKSPACE

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Copyright 2017 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
workspace(name = "io_bazel_rules_python")
15+
16+
# Imports for examples
17+
load("//python:pip.bzl", "pip_import")
18+
19+
pip_import(
20+
name = "examples_helloworld",
21+
requirements = "//examples/helloworld:requirements.txt",
22+
)
23+
24+
load(
25+
"@examples_helloworld//:requirements.bzl",
26+
_helloworld_install = "pip_install",
27+
)
28+
29+
_helloworld_install()

examples/BUILD

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Copyright 2017 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
package(default_visibility = ["//visibility:public"])
15+
16+
licenses(["notice"]) # Apache 2.0

examples/helloworld/BUILD

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Copyright 2017 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
package(default_visibility = ["//visibility:public"])
15+
16+
licenses(["notice"]) # Apache 2.0
17+
18+
load("@examples_helloworld//:requirements.bzl", "packages")
19+
load("//python:python.bzl", "py_library", "py_test")
20+
21+
py_library(
22+
name = "helloworld",
23+
srcs = ["helloworld.py"],
24+
deps = [packages("futures")],
25+
)
26+
27+
py_test(
28+
name = "helloworld_test",
29+
srcs = ["helloworld_test.py"],
30+
deps = [":helloworld"],
31+
)

examples/helloworld/helloworld.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Copyright 2017 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from concurrent import futures
16+
17+
18+
class HelloWorld(object):
19+
def __init__(self):
20+
self._threadpool = futures.ThreadPoolExecutor(max_workers=5)
21+
22+
def SayHello(self):
23+
print("Hello World")
24+
25+
def SayHelloAsync(self):
26+
self._threadpool.submit(self.SayHello)
27+
28+
def Stop(self):
29+
self._threadpool.shutdown(wait = True)
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Copyright 2017 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import unittest
16+
17+
from examples.helloworld import helloworld
18+
19+
20+
class HelloWorldTest(unittest.TestCase):
21+
22+
def test_helloworld(self):
23+
hw = helloworld.HelloWorld()
24+
hw.SayHello()
25+
26+
def test_helloworld_async(self):
27+
hw = helloworld.HelloWorld()
28+
hw.SayHelloAsync()
29+
hw.Stop()
30+
31+
def test_helloworld_multiple(self):
32+
hw = helloworld.HelloWorld()
33+
hw.SayHelloAsync()
34+
hw.SayHelloAsync()
35+
hw.SayHelloAsync()
36+
hw.SayHelloAsync()
37+
hw.Stop()
38+
39+
40+
if __name__ == '__main__':
41+
unittest.main()

examples/helloworld/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
futures>=3.1

python/BUILD

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,8 @@
1414
package(default_visibility = ["//visibility:public"])
1515

1616
licenses(["notice"]) # Apache 2.0
17+
18+
exports_files([
19+
"pip.sh",
20+
"whl.sh",
21+
])

0 commit comments

Comments
 (0)