| # Internal helpers for building the Python protobuf runtime. | 
 |  | 
 | def _internal_copy_files_impl(ctx): | 
 |     strip_prefix = ctx.attr.strip_prefix | 
 |     if strip_prefix[-1] != "/": | 
 |         strip_prefix += "/" | 
 |  | 
 |     src_dests = [] | 
 |     for src in ctx.files.srcs: | 
 |         if src.short_path[:len(strip_prefix)] != strip_prefix: | 
 |             fail("Source does not start with %s: %s" % | 
 |                  (strip_prefix, src.short_path)) | 
 |         dest = ctx.actions.declare_file(src.short_path[len(strip_prefix):]) | 
 |         src_dests.append([src, dest]) | 
 |  | 
 |     if ctx.attr.is_windows: | 
 |         bat_file = ctx.actions.declare_file(ctx.label.name + "_copy.bat") | 
 |         ctx.actions.write( | 
 |             output = bat_file, | 
 |             content = "\r\n".join([ | 
 |                 '@copy /Y "{}" "{}" >NUL'.format( | 
 |                     src.path.replace("/", "\\"), | 
 |                     dest.path.replace("/", "\\"), | 
 |                 ) | 
 |                 for src, dest in src_dests | 
 |             ]) + "\r\n", | 
 |         ) | 
 |         ctx.actions.run( | 
 |             inputs = ctx.files.srcs, | 
 |             tools = [bat_file], | 
 |             outputs = [dest for src, dest in src_dests], | 
 |             executable = "cmd.exe", | 
 |             arguments = ["/C", bat_file.path.replace("/", "\\")], | 
 |             mnemonic = "InternalCopyFile", | 
 |             progress_message = "Copying files", | 
 |             use_default_shell_env = True, | 
 |         ) | 
 |  | 
 |     else: | 
 |         sh_file = ctx.actions.declare_file(ctx.label.name + "_copy.sh") | 
 |         ctx.actions.write( | 
 |             output = sh_file, | 
 |             content = "\n".join([ | 
 |                 'cp -f "{}" "{}"'.format(src.path, dest.path) | 
 |                 for src, dest in src_dests | 
 |             ]), | 
 |         ) | 
 |         ctx.actions.run( | 
 |             inputs = ctx.files.srcs, | 
 |             tools = [sh_file], | 
 |             outputs = [dest for src, dest in src_dests], | 
 |             executable = "bash", | 
 |             arguments = [sh_file.path], | 
 |             mnemonic = "InternalCopyFile", | 
 |             progress_message = "Copying files", | 
 |             use_default_shell_env = True, | 
 |         ) | 
 |  | 
 |     return [ | 
 |         DefaultInfo(files = depset([dest for src, dest in src_dests])), | 
 |     ] | 
 |  | 
 | internal_copy_files_impl = rule( | 
 |     doc = """ | 
 | Implementation for internal_copy_files macro. | 
 |  | 
 | This rule implements file copying, including a compatibility mode for Windows. | 
 | """, | 
 |     implementation = _internal_copy_files_impl, | 
 |     attrs = { | 
 |         "srcs": attr.label_list(allow_files = True, providers = [DefaultInfo]), | 
 |         "strip_prefix": attr.string(), | 
 |         "is_windows": attr.bool(), | 
 |     }, | 
 | ) | 
 |  | 
 | def internal_copy_files(name, srcs, strip_prefix, **kwargs): | 
 |     """Copies common proto files to the python tree. | 
 |  | 
 |     In order for Python imports to work, generated proto interfaces under | 
 |     the google.protobuf package need to be in the same directory as other | 
 |     source files. This rule copies the .proto files themselves, e.g. with | 
 |     strip_prefix = 'src', 'src/google/protobuf/blah.proto' could be copied | 
 |     to '<package>/google/protobuf/blah.proto'. | 
 |  | 
 |     (An alternative might be to implement a separate rule to generate | 
 |     Python code in a different location for the sources. However, this | 
 |     would be strange behavior that doesn't match any other language's proto | 
 |     library generation.) | 
 |  | 
 |     Args: | 
 |       name: the name for the rule. | 
 |       srcs: the sources. | 
 |       strip_prefix: the prefix to remove from each of the paths in 'srcs'. The | 
 |           remainder will be used to construct the output path. | 
 |       **kwargs: common rule arguments. | 
 |  | 
 |     """ | 
 |     internal_copy_files_impl( | 
 |         name = name, | 
 |         srcs = srcs, | 
 |         strip_prefix = strip_prefix, | 
 |         is_windows = select({ | 
 |             "@bazel_tools//src/conditions:host_windows": True, | 
 |             "//conditions:default": False, | 
 |         }), | 
 |         **kwargs | 
 |     ) | 
 |  | 
 | def internal_py_test(deps = [], **kwargs): | 
 |     """Internal wrapper for shared test configuration | 
 |  | 
 |     Args: | 
 |       deps: any additional dependencies of the test. | 
 |       **kwargs: arguments forwarded to py_test. | 
 |     """ | 
 |     native.py_test( | 
 |         imports = ["."], | 
 |         deps = deps + [":python_test_lib"], | 
 |         target_compatible_with = select({ | 
 |             "@system_python//:supported": [], | 
 |             "//conditions:default": ["@platforms//:incompatible"], | 
 |         }), | 
 |         **kwargs | 
 |     ) |