Various updates build_file_generation example (#869)

* Various updates build_file_generation example

Updating the WORKSPACE file and BUILD file inline documentation.
Added new code and new directories for example.  Added new
unit test for example.
Added license headers.

* Trying to get CI to run

* Updating go and gazelle version

- updating gazelle version to 0.28
- updating go version to 1.19.4

* Getting windows to build

- added requirements_windows.txt from running //:requirements.update on
windows
- modified WORKSPACE and BUILD files to include different
requirements.update when running the build on Windows
diff --git a/.bazelrc b/.bazelrc
index cb17e8b..2ad0284 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -3,8 +3,8 @@
 # This lets us glob() up all the files inside the examples to make them inputs to tests
 # (Note, we cannot use `common --deleted_packages` because the bazel version command doesn't support it)
 # To update these lines, run tools/bazel_integration_test/update_deleted_packages.sh
-build --deleted_packages=examples/build_file_generation,examples/bzlmod,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/relative_requirements,tests/compile_pip_requirements,tests/pip_repository_entry_points,tests/pip_deps
-query --deleted_packages=examples/build_file_generation,examples/bzlmod,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/relative_requirements,tests/compile_pip_requirements,tests/pip_repository_entry_points,tests/pip_deps
+build --deleted_packages=examples/build_file_generation,examples/build_file_generation/get_url,examples/bzlmod,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/relative_requirements,tests/compile_pip_requirements,tests/pip_repository_entry_points,tests/pip_deps
+query --deleted_packages=examples/build_file_generation,examples/build_file_generation/get_url,examples/bzlmod,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/relative_requirements,tests/compile_pip_requirements,tests/pip_repository_entry_points,tests/pip_deps
 
 test --test_output=errors
 
diff --git a/examples/build_file_generation/BUILD b/examples/build_file_generation/BUILD
index 9204a0e..34449f3 100644
--- a/examples/build_file_generation/BUILD
+++ b/examples/build_file_generation/BUILD
@@ -1,9 +1,13 @@
+# Load various rules so that we can have bazel download
+# various rulesets and dependencies.
+# The `load` statement imports the symbol for the rule, in the defined
+# ruleset. When the symbol is loaded you can use the rule.
 load("@bazel_gazelle//:def.bzl", "gazelle")
 load("@pip//:requirements.bzl", "all_whl_requirements")
 load("@rules_python//gazelle:def.bzl", "GAZELLE_PYTHON_RUNTIME_DEPS")
 load("@rules_python//gazelle/manifest:defs.bzl", "gazelle_python_manifest")
 load("@rules_python//gazelle/modules_mapping:def.bzl", "modules_mapping")
-load("@rules_python//python:defs.bzl", "py_binary", "py_library")
+load("@rules_python//python:defs.bzl", "py_binary", "py_library", "py_test")
 load("@rules_python//python:pip.bzl", "compile_pip_requirements")
 
 compile_pip_requirements(
@@ -11,10 +15,13 @@
     extra_args = ["--allow-unsafe"],
     requirements_in = "requirements.txt",
     requirements_txt = "requirements_lock.txt",
+    requirements_windows = "requirements_windows.txt",
 )
 
-# This rule fetches the metadata for python packages we depend on. That data is
-# required for the gazelle_python_manifest rule to update our manifest file.
+# This repository rule fetches the metadata for python packages we
+# depend on. That data is required for the gazelle_python_manifest
+# rule to update our manifest file.
+# To see what this rule does, try `bazel run @modules_map//:print`
 modules_mapping(
     name = "modules_map",
     exclude_patterns = [
@@ -52,13 +59,25 @@
 
 # This rule is auto-generated and managed by Gazelle,
 # because it found the __init__.py file in this folder.
+# See: https://bazel.build/reference/be/python#py_library
 py_library(
     name = "build_file_generation",
     srcs = ["__init__.py"],
     visibility = ["//:__subpackages__"],
-    deps = ["@pip_requests//:pkg"],
+    deps = [
+        "//random_number_generator",
+        "@pip_flask//:pkg",
+    ],
 )
 
+# A py_binary is an executable Python program consisting of a collection of .py source files.
+# See: https://bazel.build/reference/be/python#py_binary
+#
+# This rule is auto-generated and managed by Gazelle,
+# because it found the __main__.py file in this folder.
+# This rule creates a target named //:build_file_generation_bin and you can use
+# bazel to run the target:
+# `bazel run //:build_file_generation_bin`
 py_binary(
     name = "build_file_generation_bin",
     srcs = ["__main__.py"],
@@ -66,3 +85,18 @@
     visibility = ["//:__subpackages__"],
     deps = [":build_file_generation"],
 )
+
+# A py_test is a Python unit test.
+# See: https://bazel.build/reference/be/python#py_test
+#
+# This rule is auto-generated and managed by Gazelle,
+# because it found the __test__.py file in this folder.
+# This rule creates a target named //:build_file_generation_test and you can use
+# bazel to run the target:
+# `bazel test //:build_file_generation_test`
+py_test(
+    name = "build_file_generation_test",
+    srcs = ["__test__.py"],
+    main = "__test__.py",
+    deps = [":build_file_generation"],
+)
diff --git a/examples/build_file_generation/WORKSPACE b/examples/build_file_generation/WORKSPACE
index ec5c10f..1f411d6 100644
--- a/examples/build_file_generation/WORKSPACE
+++ b/examples/build_file_generation/WORKSPACE
@@ -1,15 +1,22 @@
+# Set the name of the bazel workspace.
 workspace(name = "build_file_generation_example")
 
+# Load the http_archive rule so that we can have bazel download
+# various rulesets and dependencies.
+# The `load` statement imports the symbol for http_archive from the http.bzl
+# file.  When the symbol is loaded you can use the rule.
 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 
 ######################################################################
 # We need rules_go and bazel_gazelle, to build the gazelle plugin from source.
 # Setup instructions for this section are at
 # https://github.com/bazelbuild/bazel-gazelle#running-gazelle-with-bazel
+# You may need to update the version of the rule, which is listed in the above
+# documentation.
+######################################################################
 
-# Note, you could omit the rules_go dependency, if you have some way to statically
-# compile the gazelle binary for your workspace and distribute it to users on all
-# needed platforms.
+# Define an http_archive rule that will download the below ruleset,
+# test the sha, and extract the ruleset to you local bazel cache.
 http_archive(
     name = "io_bazel_rules_go",
     sha256 = "099a9fb96a376ccbbb7d291ed4ecbdfd42f6bc822ab77ae6f1b5cb9e914e94fa",
@@ -19,54 +26,107 @@
     ],
 )
 
+# Download the bazel_gazelle ruleset.
 http_archive(
     name = "bazel_gazelle",
-    sha256 = "efbbba6ac1a4fd342d5122cbdfdb82aeb2cf2862e35022c752eaddffada7c3f3",
+    sha256 = "448e37e0dbf61d6fa8f00aaa12d191745e14f07c31cabfa731f0c8e8a4f41b97",
     urls = [
-        "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.27.0/bazel-gazelle-v0.27.0.tar.gz",
-        "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.27.0/bazel-gazelle-v0.27.0.tar.gz",
+        "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.28.0/bazel-gazelle-v0.28.0.tar.gz",
+        "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.28.0/bazel-gazelle-v0.28.0.tar.gz",
     ],
 )
 
+# Load rules_go ruleset and expose the toolchain and dep rules.
 load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies")
 load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
 
+# go_rules_dependencies is a function that registers external dependencies
+# needed by the Go rules.
+# See: https://github.com/bazelbuild/rules_go/blob/master/go/dependencies.rst#go_rules_dependencies
 go_rules_dependencies()
 
-go_register_toolchains(version = "1.18.3")
+# go_rules_dependencies is a function that registers external dependencies
+# needed by the Go rules.
+# See: https://github.com/bazelbuild/rules_go/blob/master/go/dependencies.rst#go_rules_dependencies
+go_register_toolchains(version = "1.19.4")
 
+# The following call configured the gazelle dependencies, Go environment and Go SDK.
 gazelle_dependencies()
 
-######################################################################
-# Remaining setup is for rules_python
+# Remaining setup is for rules_python.
 
+# You do not want to use the following command when you are using a WORKSPACE file
+# that is outside of rules_python repository.
+# This command allows targets from a local directory to be bound.
+# Which allows bazel to use targets defined in base rules_python directory.
+# If you are using this example outside of the rules_python git repo,
+# use the http_archive command that is commented out below.
+# https://bazel.build/reference/be/workspace#local_repository
 local_repository(
     name = "rules_python",
     path = "../..",
 )
 
+# When not using this example in the rules_python git repo you would load the python
+# ruleset using the following StarLark.
+# See https://github.com/bazelbuild/rules_python#getting-started for the latest
+# ruleset version.
+#
+# The following StarLark would replace the `local_repository` rule mentioned above.
+#
+# load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+# http_archive(
+#     name = "rules_python",
+#     sha256 = "497ca47374f48c8b067d786b512ac10a276211810f4a580178ee9b9ad139323a",
+#     strip_prefix = "rules_python-0.16.1",
+#     url = "https://github.com/bazelbuild/rules_python/archive/refs/tags/0.16.1.tar.gz",
+# )
+
+# Next we load the toolchain from rules_python.
 load("@rules_python//python:repositories.bzl", "python_register_toolchains")
 
+# We now register a hermetic Python interpreter rather than relying on a system-installed interpreter.
+# This toolchain will allow bazel to download a specific python version, and use that version
+# for compilation.
 python_register_toolchains(
     name = "python39",
     python_version = "3.9",
 )
 
+# Load the interpreter and pip_parse rules.
 load("@python39//:defs.bzl", "interpreter")
 load("@rules_python//python:pip.bzl", "pip_parse")
 
+# This macro wraps the `pip_repository` rule that invokes `pip`, with `incremental` set.
+# Accepts a locked/compiled requirements file and installs the dependencies listed within.
+# Those dependencies become available in a generated `requirements.bzl` file.
+# You can instead check this `requirements.bzl` file into your repo.
 pip_parse(
     name = "pip",
+    # (Optional) You can provide a python_interpreter (path) or a python_interpreter_target (a Bazel target, that
+    # acts as an executable). The latter can be anything that could be used as Python interpreter. E.g.:
+    # 1. Python interpreter that you compile in the build file.
+    # 2. Pre-compiled python interpreter included with http_archive.
+    # 3. Wrapper script, like in the autodetecting python toolchain.
+    #
+    # Here, we use the interpreter constant that resolves to the host interpreter from the default Python toolchain.
     python_interpreter_target = interpreter,
+    # Set the location of the lock file.
     requirements_lock = "//:requirements_lock.txt",
+    requirements_windows = "//:requirements_windows.txt",
 )
 
+# Load the install_deps macro.
 load("@pip//:requirements.bzl", "install_deps")
 
+# Initialize repositories for all packages in requirements_lock.txt.
 install_deps()
 
 # The rules_python gazelle extension has some third-party go dependencies
 # which we need to fetch in order to compile it.
 load("@rules_python//gazelle:deps.bzl", _py_gazelle_deps = "gazelle_deps")
 
+# See: https://github.com/bazelbuild/rules_python/blob/main/gazelle/README.md
+# This rule loads and compiles various go dependencies that running gazelle
+# for python requirements.
 _py_gazelle_deps()
diff --git a/examples/build_file_generation/__init__.py b/examples/build_file_generation/__init__.py
index 6dfd77c..add73da 100644
--- a/examples/build_file_generation/__init__.py
+++ b/examples/build_file_generation/__init__.py
@@ -1,6 +1,26 @@
-import requests
+# Copyright 2022 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
 
+from flask import Flask, jsonify
+from random_number_generator import generate_random_number
 
-def main(url):
-    r = requests.get(url)
-    print(r.text)
+app = Flask(__name__)
+
+@app.route('/random-number', methods=['GET'])
+def get_random_number():
+    return jsonify({'number': generate_random_number.generate_random_number()})
+
+"""Start the python web server"""
+def main():
+    app.run()
diff --git a/examples/build_file_generation/__main__.py b/examples/build_file_generation/__main__.py
index 106c836..8f8efba 100644
--- a/examples/build_file_generation/__main__.py
+++ b/examples/build_file_generation/__main__.py
@@ -1,4 +1,18 @@
+# Copyright 2022 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 from __init__ import main
 
-if __name__ == "__main__":
-    main("https://example.com")
+if __name__ == '__main__':
+    main()
diff --git a/examples/build_file_generation/__test__.py b/examples/build_file_generation/__test__.py
new file mode 100644
index 0000000..c4fa5ef
--- /dev/null
+++ b/examples/build_file_generation/__test__.py
@@ -0,0 +1,28 @@
+# Copyright 2022 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+from __init__ import app
+
+class TestServer(unittest.TestCase):
+    def setUp(self):
+        self.app = app.test_client()
+        
+    def test_get_random_number(self):
+        response = self.app.get('/random-number')
+        self.assertEqual(response.status_code, 200)
+        self.assertIn('number', response.json)
+        
+if __name__ == '__main__':
+    unittest.main()
diff --git a/examples/build_file_generation/gazelle_python.yaml b/examples/build_file_generation/gazelle_python.yaml
index f25f59e..46d1d64 100644
--- a/examples/build_file_generation/gazelle_python.yaml
+++ b/examples/build_file_generation/gazelle_python.yaml
@@ -5,107 +5,114 @@
 
 manifest:
   modules_mapping:
-    certifi: certifi
-    certifi.core: certifi
-    chardet: chardet
-    chardet.big5freq: chardet
-    chardet.big5prober: chardet
-    chardet.chardistribution: chardet
-    chardet.charsetgroupprober: chardet
-    chardet.charsetprober: chardet
-    chardet.cli: chardet
-    chardet.cli.chardetect: chardet
-    chardet.codingstatemachine: chardet
-    chardet.compat: chardet
-    chardet.cp949prober: chardet
-    chardet.enums: chardet
-    chardet.escprober: chardet
-    chardet.escsm: chardet
-    chardet.eucjpprober: chardet
-    chardet.euckrfreq: chardet
-    chardet.euckrprober: chardet
-    chardet.euctwfreq: chardet
-    chardet.euctwprober: chardet
-    chardet.gb2312freq: chardet
-    chardet.gb2312prober: chardet
-    chardet.hebrewprober: chardet
-    chardet.jisfreq: chardet
-    chardet.jpcntx: chardet
-    chardet.langbulgarianmodel: chardet
-    chardet.langcyrillicmodel: chardet
-    chardet.langgreekmodel: chardet
-    chardet.langhebrewmodel: chardet
-    chardet.langhungarianmodel: chardet
-    chardet.langthaimodel: chardet
-    chardet.langturkishmodel: chardet
-    chardet.latin1prober: chardet
-    chardet.mbcharsetprober: chardet
-    chardet.mbcsgroupprober: chardet
-    chardet.mbcssm: chardet
-    chardet.sbcharsetprober: chardet
-    chardet.sbcsgroupprober: chardet
-    chardet.sjisprober: chardet
-    chardet.universaldetector: chardet
-    chardet.utf8prober: chardet
-    chardet.version: chardet
-    idna: idna
-    idna.codec: idna
-    idna.compat: idna
-    idna.core: idna
-    idna.idnadata: idna
-    idna.intranges: idna
-    idna.package_data: idna
-    idna.uts46data: idna
-    psutil: psutil
-    requests: requests
-    requests.adapters: requests
-    requests.api: requests
-    requests.auth: requests
-    requests.certs: requests
-    requests.compat: requests
-    requests.cookies: requests
-    requests.exceptions: requests
-    requests.help: requests
-    requests.hooks: requests
-    requests.models: requests
-    requests.packages: requests
-    requests.sessions: requests
-    requests.status_codes: requests
-    requests.structures: requests
-    requests.utils: requests
-    urllib3: urllib3
-    urllib3.connection: urllib3
-    urllib3.connectionpool: urllib3
-    urllib3.contrib: urllib3
-    urllib3.contrib.appengine: urllib3
-    urllib3.contrib.ntlmpool: urllib3
-    urllib3.contrib.pyopenssl: urllib3
-    urllib3.contrib.securetransport: urllib3
-    urllib3.contrib.socks: urllib3
-    urllib3.exceptions: urllib3
-    urllib3.fields: urllib3
-    urllib3.filepost: urllib3
-    urllib3.packages: urllib3
-    urllib3.packages.backports: urllib3
-    urllib3.packages.backports.makefile: urllib3
-    urllib3.packages.six: urllib3
-    urllib3.packages.ssl_match_hostname: urllib3
-    urllib3.poolmanager: urllib3
-    urllib3.request: urllib3
-    urllib3.response: urllib3
-    urllib3.util: urllib3
-    urllib3.util.connection: urllib3
-    urllib3.util.proxy: urllib3
-    urllib3.util.queue: urllib3
-    urllib3.util.request: urllib3
-    urllib3.util.response: urllib3
-    urllib3.util.retry: urllib3
-    urllib3.util.ssl_: urllib3
-    urllib3.util.ssltransport: urllib3
-    urllib3.util.timeout: urllib3
-    urllib3.util.url: urllib3
-    urllib3.util.wait: urllib3
+    click: click
+    click.core: click
+    click.decorators: click
+    click.exceptions: click
+    click.formatting: click
+    click.globals: click
+    click.parser: click
+    click.shell_completion: click
+    click.termui: click
+    click.testing: click
+    click.types: click
+    click.utils: click
+    flask: Flask
+    flask.app: Flask
+    flask.blueprints: Flask
+    flask.cli: Flask
+    flask.config: Flask
+    flask.ctx: Flask
+    flask.debughelpers: Flask
+    flask.globals: Flask
+    flask.helpers: Flask
+    flask.json: Flask
+    flask.json.provider: Flask
+    flask.json.tag: Flask
+    flask.logging: Flask
+    flask.scaffold: Flask
+    flask.sessions: Flask
+    flask.signals: Flask
+    flask.templating: Flask
+    flask.testing: Flask
+    flask.typing: Flask
+    flask.views: Flask
+    flask.wrappers: Flask
+    importlib_metadata: importlib_metadata
+    itsdangerous: itsdangerous
+    itsdangerous.encoding: itsdangerous
+    itsdangerous.exc: itsdangerous
+    itsdangerous.serializer: itsdangerous
+    itsdangerous.signer: itsdangerous
+    itsdangerous.timed: itsdangerous
+    itsdangerous.url_safe: itsdangerous
+    jinja2: Jinja2
+    jinja2.async_utils: Jinja2
+    jinja2.bccache: Jinja2
+    jinja2.compiler: Jinja2
+    jinja2.constants: Jinja2
+    jinja2.debug: Jinja2
+    jinja2.defaults: Jinja2
+    jinja2.environment: Jinja2
+    jinja2.exceptions: Jinja2
+    jinja2.ext: Jinja2
+    jinja2.filters: Jinja2
+    jinja2.idtracking: Jinja2
+    jinja2.lexer: Jinja2
+    jinja2.loaders: Jinja2
+    jinja2.meta: Jinja2
+    jinja2.nativetypes: Jinja2
+    jinja2.nodes: Jinja2
+    jinja2.optimizer: Jinja2
+    jinja2.parser: Jinja2
+    jinja2.runtime: Jinja2
+    jinja2.sandbox: Jinja2
+    jinja2.utils: Jinja2
+    jinja2.visitor: Jinja2
+    markupsafe: MarkupSafe
+    werkzeug: Werkzeug
+    werkzeug.datastructures: Werkzeug
+    werkzeug.debug: Werkzeug
+    werkzeug.debug.console: Werkzeug
+    werkzeug.debug.repr: Werkzeug
+    werkzeug.debug.tbtools: Werkzeug
+    werkzeug.exceptions: Werkzeug
+    werkzeug.formparser: Werkzeug
+    werkzeug.http: Werkzeug
+    werkzeug.local: Werkzeug
+    werkzeug.middleware: Werkzeug
+    werkzeug.middleware.dispatcher: Werkzeug
+    werkzeug.middleware.http_proxy: Werkzeug
+    werkzeug.middleware.lint: Werkzeug
+    werkzeug.middleware.profiler: Werkzeug
+    werkzeug.middleware.proxy_fix: Werkzeug
+    werkzeug.middleware.shared_data: Werkzeug
+    werkzeug.routing: Werkzeug
+    werkzeug.routing.converters: Werkzeug
+    werkzeug.routing.exceptions: Werkzeug
+    werkzeug.routing.map: Werkzeug
+    werkzeug.routing.matcher: Werkzeug
+    werkzeug.routing.rules: Werkzeug
+    werkzeug.sansio: Werkzeug
+    werkzeug.sansio.http: Werkzeug
+    werkzeug.sansio.multipart: Werkzeug
+    werkzeug.sansio.request: Werkzeug
+    werkzeug.sansio.response: Werkzeug
+    werkzeug.sansio.utils: Werkzeug
+    werkzeug.security: Werkzeug
+    werkzeug.serving: Werkzeug
+    werkzeug.test: Werkzeug
+    werkzeug.testapp: Werkzeug
+    werkzeug.urls: Werkzeug
+    werkzeug.user_agent: Werkzeug
+    werkzeug.utils: Werkzeug
+    werkzeug.wrappers: Werkzeug
+    werkzeug.wrappers.request: Werkzeug
+    werkzeug.wrappers.response: Werkzeug
+    werkzeug.wsgi: Werkzeug
+    zipp: zipp
+    zipp.py310compat: zipp
   pip_repository:
     name: pip
     incremental: true
-integrity: 91adaddb7e2d3eb7234e78979ff40b666101ab4df91c62659b954cc9376c2f86
+integrity: 9bb7b166e9358f3244c9beae2a863084fe4e58c31d3ccb65618dd471512fdb5e
diff --git a/examples/build_file_generation/random_number_generator/BUILD b/examples/build_file_generation/random_number_generator/BUILD
new file mode 100644
index 0000000..95e16fd
--- /dev/null
+++ b/examples/build_file_generation/random_number_generator/BUILD
@@ -0,0 +1,19 @@
+load("@rules_python//python:defs.bzl", "py_library", "py_test")
+
+py_library(
+    name = "random_number_generator",
+    srcs = [
+        "__init__.py",
+        "generate_random_number.py",
+    ],
+    imports = [".."],
+    visibility = ["//:__subpackages__"],
+)
+
+py_test(
+    name = "random_number_generator_test",
+    srcs = ["__test__.py"],
+    imports = [".."],
+    main = "__test__.py",
+    deps = [":random_number_generator"],
+)
diff --git a/examples/build_file_generation/random_number_generator/__init__.py b/examples/build_file_generation/random_number_generator/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/examples/build_file_generation/random_number_generator/__init__.py
diff --git a/examples/build_file_generation/random_number_generator/__test__.py b/examples/build_file_generation/random_number_generator/__test__.py
new file mode 100644
index 0000000..8cfb235
--- /dev/null
+++ b/examples/build_file_generation/random_number_generator/__test__.py
@@ -0,0 +1,25 @@
+# Copyright 2022 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+import random_number_generator.generate_random_number as generate_random_number
+
+class TestRandomNumberGenerator(unittest.TestCase):
+    def test_generate_random_number(self):
+        number = generate_random_number.generate_random_number()
+        self.assertGreaterEqual(number, 1)
+        self.assertLessEqual(number, 10)
+        
+if __name__ == '__main__':
+    unittest.main()
diff --git a/examples/build_file_generation/random_number_generator/generate_random_number.py b/examples/build_file_generation/random_number_generator/generate_random_number.py
new file mode 100644
index 0000000..e198b5b
--- /dev/null
+++ b/examples/build_file_generation/random_number_generator/generate_random_number.py
@@ -0,0 +1,19 @@
+# Copyright 2022 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import random
+
+"""Generate a random number"""
+def generate_random_number():
+    return random.randint(1, 10)
diff --git a/examples/build_file_generation/requirements.txt b/examples/build_file_generation/requirements.txt
index 2851c1e..7e10602 100644
--- a/examples/build_file_generation/requirements.txt
+++ b/examples/build_file_generation/requirements.txt
@@ -1,2 +1 @@
-requests==2.25.1
-psutil==5.9.4
+flask
diff --git a/examples/build_file_generation/requirements_lock.txt b/examples/build_file_generation/requirements_lock.txt
index 07ff2ec..f4a29bd 100644
--- a/examples/build_file_generation/requirements_lock.txt
+++ b/examples/build_file_generation/requirements_lock.txt
@@ -4,39 +4,75 @@
 #
 #    bazel run //:requirements.update
 #
-certifi==2020.12.5 \
-    --hash=sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c \
-    --hash=sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830
-    # via requests
-chardet==3.0.4 \
-    --hash=sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae \
-    --hash=sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691
-    # via requests
-idna==2.10 \
-    --hash=sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6 \
-    --hash=sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0
-    # via requests
-psutil==5.9.4 \
-    --hash=sha256:149555f59a69b33f056ba1c4eb22bb7bf24332ce631c44a319cec09f876aaeff \
-    --hash=sha256:16653106f3b59386ffe10e0bad3bb6299e169d5327d3f187614b1cb8f24cf2e1 \
-    --hash=sha256:3d7f9739eb435d4b1338944abe23f49584bde5395f27487d2ee25ad9a8774a62 \
-    --hash=sha256:3ff89f9b835100a825b14c2808a106b6fdcc4b15483141482a12c725e7f78549 \
-    --hash=sha256:54c0d3d8e0078b7666984e11b12b88af2db11d11249a8ac8920dd5ef68a66e08 \
-    --hash=sha256:54d5b184728298f2ca8567bf83c422b706200bcbbfafdc06718264f9393cfeb7 \
-    --hash=sha256:6001c809253a29599bc0dfd5179d9f8a5779f9dffea1da0f13c53ee568115e1e \
-    --hash=sha256:68908971daf802203f3d37e78d3f8831b6d1014864d7a85937941bb35f09aefe \
-    --hash=sha256:6b92c532979bafc2df23ddc785ed116fced1f492ad90a6830cf24f4d1ea27d24 \
-    --hash=sha256:852dd5d9f8a47169fe62fd4a971aa07859476c2ba22c2254d4a1baa4e10b95ad \
-    --hash=sha256:9120cd39dca5c5e1c54b59a41d205023d436799b1c8c4d3ff71af18535728e94 \
-    --hash=sha256:c1ca331af862803a42677c120aff8a814a804e09832f166f226bfd22b56feee8 \
-    --hash=sha256:efeae04f9516907be44904cc7ce08defb6b665128992a56957abc9b61dca94b7 \
-    --hash=sha256:fd8522436a6ada7b4aad6638662966de0d61d241cb821239b2ae7013d41a43d4
+click==8.1.3 \
+    --hash=sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e \
+    --hash=sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48
+    # via flask
+flask==2.2.2 \
+    --hash=sha256:642c450d19c4ad482f96729bd2a8f6d32554aa1e231f4f6b4e7e5264b16cca2b \
+    --hash=sha256:b9c46cc36662a7949f34b52d8ec7bb59c0d74ba08ba6cb9ce9adc1d8676d9526
     # via -r ./requirements.txt
-requests==2.25.1 \
-    --hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \
-    --hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e
-    # via -r ./requirements.txt
-urllib3==1.26.5 \
-    --hash=sha256:753a0374df26658f99d826cfe40394a686d05985786d946fbe4165b5148f5a7c \
-    --hash=sha256:a7acd0977125325f516bda9735fa7142b909a8d01e8b2e4c8108d0984e6e0098
-    # via requests
+importlib-metadata==5.1.0 \
+    --hash=sha256:d5059f9f1e8e41f80e9c56c2ee58811450c31984dfa625329ffd7c0dad88a73b \
+    --hash=sha256:d84d17e21670ec07990e1044a99efe8d615d860fd176fc29ef5c306068fda313
+    # via flask
+itsdangerous==2.1.2 \
+    --hash=sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44 \
+    --hash=sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a
+    # via flask
+jinja2==3.1.2 \
+    --hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \
+    --hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61
+    # via flask
+markupsafe==2.1.1 \
+    --hash=sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003 \
+    --hash=sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88 \
+    --hash=sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5 \
+    --hash=sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7 \
+    --hash=sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a \
+    --hash=sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603 \
+    --hash=sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1 \
+    --hash=sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135 \
+    --hash=sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247 \
+    --hash=sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6 \
+    --hash=sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601 \
+    --hash=sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77 \
+    --hash=sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02 \
+    --hash=sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e \
+    --hash=sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63 \
+    --hash=sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f \
+    --hash=sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980 \
+    --hash=sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b \
+    --hash=sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812 \
+    --hash=sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff \
+    --hash=sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96 \
+    --hash=sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1 \
+    --hash=sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925 \
+    --hash=sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a \
+    --hash=sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6 \
+    --hash=sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e \
+    --hash=sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f \
+    --hash=sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4 \
+    --hash=sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f \
+    --hash=sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3 \
+    --hash=sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c \
+    --hash=sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a \
+    --hash=sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417 \
+    --hash=sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a \
+    --hash=sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a \
+    --hash=sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37 \
+    --hash=sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452 \
+    --hash=sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933 \
+    --hash=sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a \
+    --hash=sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7
+    # via
+    #   jinja2
+    #   werkzeug
+werkzeug==2.2.2 \
+    --hash=sha256:7ea2d48322cc7c0f8b3a215ed73eabd7b5d75d0b50e31ab006286ccff9e00b8f \
+    --hash=sha256:f979ab81f58d7318e064e99c4506445d60135ac5cd2e177a2de0089bfd4c9bd5
+    # via flask
+zipp==3.11.0 \
+    --hash=sha256:83a28fcb75844b5c0cdaf5aa4003c2d728c77e05f5aeabe8e95e56727005fbaa \
+    --hash=sha256:a7a22e05929290a67401440b39690ae6563279bced5f314609d9d03798f56766
+    # via importlib-metadata
diff --git a/examples/build_file_generation/requirements_windows.txt b/examples/build_file_generation/requirements_windows.txt
new file mode 100644
index 0000000..4f6d590
--- /dev/null
+++ b/examples/build_file_generation/requirements_windows.txt
@@ -0,0 +1,82 @@
+#

+# This file is autogenerated by pip-compile with python 3.9

+# To update, run:

+#

+#    bazel run //:requirements.update

+#

+click==8.1.3 \

+    --hash=sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e \

+    --hash=sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48

+    # via flask

+colorama==0.4.6 \

+    --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \

+    --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6

+    # via click

+flask==2.2.2 \

+    --hash=sha256:642c450d19c4ad482f96729bd2a8f6d32554aa1e231f4f6b4e7e5264b16cca2b \

+    --hash=sha256:b9c46cc36662a7949f34b52d8ec7bb59c0d74ba08ba6cb9ce9adc1d8676d9526

+    # via -r ./requirements.txt

+importlib-metadata==5.1.0 \

+    --hash=sha256:d5059f9f1e8e41f80e9c56c2ee58811450c31984dfa625329ffd7c0dad88a73b \

+    --hash=sha256:d84d17e21670ec07990e1044a99efe8d615d860fd176fc29ef5c306068fda313

+    # via flask

+itsdangerous==2.1.2 \

+    --hash=sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44 \

+    --hash=sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a

+    # via flask

+jinja2==3.1.2 \

+    --hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \

+    --hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61

+    # via flask

+markupsafe==2.1.1 \

+    --hash=sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003 \

+    --hash=sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88 \

+    --hash=sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5 \

+    --hash=sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7 \

+    --hash=sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a \

+    --hash=sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603 \

+    --hash=sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1 \

+    --hash=sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135 \

+    --hash=sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247 \

+    --hash=sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6 \

+    --hash=sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601 \

+    --hash=sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77 \

+    --hash=sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02 \

+    --hash=sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e \

+    --hash=sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63 \

+    --hash=sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f \

+    --hash=sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980 \

+    --hash=sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b \

+    --hash=sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812 \

+    --hash=sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff \

+    --hash=sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96 \

+    --hash=sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1 \

+    --hash=sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925 \

+    --hash=sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a \

+    --hash=sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6 \

+    --hash=sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e \

+    --hash=sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f \

+    --hash=sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4 \

+    --hash=sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f \

+    --hash=sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3 \

+    --hash=sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c \

+    --hash=sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a \

+    --hash=sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417 \

+    --hash=sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a \

+    --hash=sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a \

+    --hash=sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37 \

+    --hash=sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452 \

+    --hash=sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933 \

+    --hash=sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a \

+    --hash=sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7

+    # via

+    #   jinja2

+    #   werkzeug

+werkzeug==2.2.2 \

+    --hash=sha256:7ea2d48322cc7c0f8b3a215ed73eabd7b5d75d0b50e31ab006286ccff9e00b8f \

+    --hash=sha256:f979ab81f58d7318e064e99c4506445d60135ac5cd2e177a2de0089bfd4c9bd5

+    # via flask

+zipp==3.11.0 \

+    --hash=sha256:83a28fcb75844b5c0cdaf5aa4003c2d728c77e05f5aeabe8e95e56727005fbaa \

+    --hash=sha256:a7a22e05929290a67401440b39690ae6563279bced5f314609d9d03798f56766

+    # via importlib-metadata

diff --git a/examples/pip_parse_vendored/requirements.bzl b/examples/pip_parse_vendored/requirements.bzl
index 5a0dcf8..4febc75 100644
--- a/examples/pip_parse_vendored/requirements.bzl
+++ b/examples/pip_parse_vendored/requirements.bzl
@@ -1,7 +1,7 @@
 """Starlark representation of locked requirements.
 
 @generated by rules_python pip_parse repository rule
-from //:requirements.txt
+from @//:requirements.txt
 """
 
 load("@python39//:defs.bzl", "interpreter")