diff options
Diffstat (limited to 'python')
| -rw-r--r-- | python/androidmk.go | 2 | ||||
| -rw-r--r-- | python/binary.go | 33 | ||||
| -rw-r--r-- | python/builder.go | 26 | ||||
| -rw-r--r-- | python/defaults.go | 11 | ||||
| -rw-r--r-- | python/library.go | 11 | ||||
| -rw-r--r-- | python/proto.go | 5 | ||||
| -rw-r--r-- | python/python.go | 82 | ||||
| -rw-r--r-- | python/python_test.go | 2 | ||||
| -rw-r--r-- | python/scripts/main_non_embedded.py | 6 | ||||
| -rw-r--r-- | python/scripts/stub_template_host.txt | 68 | ||||
| -rw-r--r-- | python/test.go | 8 | ||||
| -rw-r--r-- | python/tests/dont_import_folder_of_entrypoint/Android.bp | 26 | ||||
| -rw-r--r-- | python/tests/dont_import_folder_of_entrypoint/mypkg/main.py | 15 | ||||
| -rw-r--r-- | python/tests/dont_import_folder_of_entrypoint/mypkg/mymodule.py | 0 | ||||
| -rw-r--r-- | python/tests/proto_pkg_path/Android.bp | 16 | ||||
| -rw-r--r-- | python/tests/proto_pkg_path/main.py | 18 | ||||
| -rw-r--r-- | python/tests/proto_pkg_path/proto/common.proto | 5 | ||||
| -rw-r--r-- | python/tests/proto_pkg_path/proto/test.proto | 8 | ||||
| -rw-r--r-- | python/tests/top_level_dirs/Android.bp | 12 | ||||
| -rw-r--r-- | python/tests/top_level_dirs/main.py | 17 | ||||
| -rw-r--r-- | python/tests/top_level_dirs/mypkg/mymodule.py | 0 |
21 files changed, 248 insertions, 123 deletions
diff --git a/python/androidmk.go b/python/androidmk.go index 233d8679f..7dc471397 100644 --- a/python/androidmk.go +++ b/python/androidmk.go @@ -69,7 +69,7 @@ func (p *testDecorator) AndroidMk(base *Module, entries *android.AndroidMkEntrie entries.AddStrings("LOCAL_TEST_DATA", android.AndroidMkDataPaths(p.data)...) - entries.SetBoolIfTrue("LOCAL_IS_UNIT_TEST", Bool(p.testProperties.Test_options.Unit_test)) + p.testProperties.Test_options.SetAndroidMkEntries(entries) }) base.subAndroidMk(entries, p.binaryDecorator.pythonInstaller) } diff --git a/python/binary.go b/python/binary.go index 99c625916..670e0d313 100644 --- a/python/binary.go +++ b/python/binary.go @@ -34,24 +34,14 @@ func registerPythonBinaryComponents(ctx android.RegistrationContext) { } type bazelPythonBinaryAttributes struct { - Main *string + Main *bazel.Label Srcs bazel.LabelListAttribute Deps bazel.LabelListAttribute Python_version *string + Imports bazel.StringListAttribute } func pythonBinaryBp2Build(ctx android.TopDownMutatorContext, m *Module) { - var main *string - for _, propIntf := range m.GetProperties() { - if props, ok := propIntf.(*BinaryProperties); ok { - // main is optional. - if props.Main != nil { - main = props.Main - break - } - } - } - // TODO(b/182306917): this doesn't fully handle all nested props versioned // by the python version, which would have been handled by the version split // mutator. This is sufficient for very simple python_binary_host modules @@ -71,10 +61,22 @@ func pythonBinaryBp2Build(ctx android.TopDownMutatorContext, m *Module) { baseAttrs := m.makeArchVariantBaseAttributes(ctx) attrs := &bazelPythonBinaryAttributes{ - Main: main, + Main: nil, Srcs: baseAttrs.Srcs, Deps: baseAttrs.Deps, Python_version: python_version, + Imports: baseAttrs.Imports, + } + + for _, propIntf := range m.GetProperties() { + if props, ok := propIntf.(*BinaryProperties); ok { + // main is optional. + if props.Main != nil { + main := android.BazelLabelForModuleSrcSingle(ctx, *props.Main) + attrs.Main = &main + break + } + } } props := bazel.BazelTargetModuleProperties{ @@ -126,10 +128,6 @@ type IntermPathProvider interface { IntermPathForModuleOut() android.OptionalPath } -var ( - StubTemplateHost = "build/soong/python/scripts/stub_template_host.txt" -) - func NewBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) { module := newModule(hod, android.MultilibFirst) decorator := &binaryDecorator{pythonInstaller: NewPythonInstaller("bin", "")} @@ -177,7 +175,6 @@ func (binary *binaryDecorator) bootstrap(ctx android.ModuleContext, actualVersio } }) } - binFile := registerBuildActionForParFile(ctx, embeddedLauncher, launcherPath, binary.getHostInterpreterName(ctx, actualVersion), main, binary.getStem(ctx), append(android.Paths{srcsZip}, depsSrcsZips...)) diff --git a/python/builder.go b/python/builder.go index 7d7239c55..b4ab20691 100644 --- a/python/builder.go +++ b/python/builder.go @@ -20,7 +20,6 @@ import ( "strings" "android/soong/android" - "github.com/google/blueprint" _ "github.com/google/blueprint/bootstrap" ) @@ -44,13 +43,15 @@ var ( hostPar = pctx.AndroidStaticRule("hostPar", blueprint.RuleParams{ - Command: `sed -e 's/%interpreter%/$interp/g' -e 's/%main%/$main/g' $template > $stub && ` + + Command: `sed -e 's/%interpreter%/$interp/g' -e 's/%main%/__soong_entrypoint_redirector__.py/g' build/soong/python/scripts/stub_template_host.txt > $out.main && ` + + "sed -e 's/ENTRY_POINT/$main/g' build/soong/python/scripts/main_non_embedded.py >`dirname $out`/__soong_entrypoint_redirector__.py && " + + "$parCmd -o $out.entrypoint_zip -C `dirname $out` -f `dirname $out`/__soong_entrypoint_redirector__.py && " + `echo "#!/usr/bin/env $interp" >${out}.prefix &&` + - `$mergeParCmd -p --prefix ${out}.prefix -pm $stub $out $srcsZips && ` + - `chmod +x $out && (rm -f $stub; rm -f ${out}.prefix)`, - CommandDeps: []string{"$mergeParCmd"}, + `$mergeParCmd -p --prefix ${out}.prefix -pm $out.main $out $srcsZips $out.entrypoint_zip && ` + + "chmod +x $out && (rm -f $out.main; rm -f ${out}.prefix; rm -f $out.entrypoint_zip; rm -f `dirname $out`/__soong_entrypoint_redirector__.py)", + CommandDeps: []string{"$mergeParCmd", "$parCmd", "build/soong/python/scripts/stub_template_host.txt", "build/soong/python/scripts/main_non_embedded.py"}, }, - "interp", "main", "template", "stub", "srcsZips") + "interp", "main", "srcsZips") embeddedPar = pctx.AndroidStaticRule("embeddedPar", blueprint.RuleParams{ @@ -58,7 +59,7 @@ var ( `sed 's/ENTRY_POINT/$main/' build/soong/python/scripts/main.py >$out.main &&` + `$mergeParCmd -p -pm $out.main --prefix $launcher $out $srcsZips && ` + `chmod +x $out && rm -rf $out.main`, - CommandDeps: []string{"$mergeParCmd", "$parCmd", "build/soong/python/scripts/main.py"}, + CommandDeps: []string{"$mergeParCmd", "build/soong/python/scripts/main.py"}, }, "main", "srcsZips", "launcher") @@ -90,13 +91,6 @@ func registerBuildActionForParFile(ctx android.ModuleContext, embeddedLauncher b implicits := srcsZips if !embeddedLauncher { - // the path of stub_template_host.txt from source tree. - template := android.PathForSource(ctx, StubTemplateHost) - implicits = append(implicits, template) - - // intermediate output path for __main__.py - stub := android.PathForModuleOut(ctx, mainFileName).String() - ctx.Build(pctx, android.BuildParams{ Rule: hostPar, Description: "host python archive", @@ -104,9 +98,7 @@ func registerBuildActionForParFile(ctx android.ModuleContext, embeddedLauncher b Implicits: implicits, Args: map[string]string{ "interp": strings.Replace(interpreter, "/", `\/`, -1), - "main": strings.Replace(main, "/", `\/`, -1), - "template": template.String(), - "stub": stub, + "main": strings.Replace(strings.TrimSuffix(main, pyExt), "/", ".", -1), "srcsZips": strings.Join(srcsZips.Strings(), " "), }, }) diff --git a/python/defaults.go b/python/defaults.go index dba23a729..3dc5bc4d2 100644 --- a/python/defaults.go +++ b/python/defaults.go @@ -19,7 +19,7 @@ import ( ) func init() { - android.RegisterModuleType("python_defaults", defaultsFactory) + android.RegisterModuleType("python_defaults", DefaultsFactory) } type Defaults struct { @@ -30,16 +30,13 @@ type Defaults struct { func (d *Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) { } -func defaultsFactory() android.Module { - return DefaultsFactory() -} - -func DefaultsFactory(props ...interface{}) android.Module { +func DefaultsFactory() android.Module { module := &Defaults{} - module.AddProperties(props...) module.AddProperties( &BaseProperties{}, + &android.ProtoProperties{}, + &BinaryProperties{}, ) android.InitDefaultsModule(module) diff --git a/python/library.go b/python/library.go index d026c1323..df92df42b 100644 --- a/python/library.go +++ b/python/library.go @@ -43,9 +43,14 @@ func PythonLibraryHostFactory() android.Module { type bazelPythonLibraryAttributes struct { Srcs bazel.LabelListAttribute Deps bazel.LabelListAttribute + Imports bazel.StringListAttribute Srcs_version *string } +type bazelPythonProtoLibraryAttributes struct { + Deps bazel.LabelListAttribute +} + func pythonLibBp2Build(ctx android.TopDownMutatorContext, m *Module) { // TODO(b/182306917): this doesn't fully handle all nested props versioned // by the python version, which would have been handled by the version split @@ -65,15 +70,17 @@ func pythonLibBp2Build(ctx android.TopDownMutatorContext, m *Module) { } baseAttrs := m.makeArchVariantBaseAttributes(ctx) + attrs := &bazelPythonLibraryAttributes{ Srcs: baseAttrs.Srcs, Deps: baseAttrs.Deps, Srcs_version: python_version, + Imports: baseAttrs.Imports, } props := bazel.BazelTargetModuleProperties{ - Rule_class: "py_library", - Bzl_load_location: "//build/bazel/rules/python:library.bzl", + // Use the native py_library rule. + Rule_class: "py_library", } ctx.CreateBazelTargetModule(props, android.CommonAttributes{ diff --git a/python/proto.go b/python/proto.go index 53ebb5895..400e72c99 100644 --- a/python/proto.go +++ b/python/proto.go @@ -18,7 +18,7 @@ import ( "android/soong/android" ) -func genProto(ctx android.ModuleContext, protoFile android.Path, flags android.ProtoFlags, pkgPath string) android.Path { +func genProto(ctx android.ModuleContext, protoFile android.Path, flags android.ProtoFlags) android.Path { srcsZipFile := android.PathForModuleGen(ctx, protoFile.Base()+".srcszip") outDir := srcsZipFile.ReplaceExtension(ctx, "tmp") @@ -36,9 +36,6 @@ func genProto(ctx android.ModuleContext, protoFile android.Path, flags android.P zipCmd := rule.Command(). BuiltTool("soong_zip"). FlagWithOutput("-o ", srcsZipFile) - if pkgPath != "" { - zipCmd.FlagWithArg("-P ", pkgPath) - } zipCmd.FlagWithArg("-C ", outDir.String()). FlagWithArg("-D ", outDir.String()) diff --git a/python/python.go b/python/python.go index b100cc318..24e1bb2ec 100644 --- a/python/python.go +++ b/python/python.go @@ -131,7 +131,8 @@ type baseAttributes struct { Srcs bazel.LabelListAttribute Deps bazel.LabelListAttribute // Combines Data and Java_data (invariant) - Data bazel.LabelListAttribute + Data bazel.LabelListAttribute + Imports bazel.StringListAttribute } // Used to store files of current module after expanding dependencies @@ -207,6 +208,56 @@ func (m *Module) makeArchVariantBaseAttributes(ctx android.TopDownMutatorContext } } } + + partitionedSrcs := bazel.PartitionLabelListAttribute(ctx, &attrs.Srcs, bazel.LabelPartitions{ + "proto": android.ProtoSrcLabelPartition, + "py": bazel.LabelPartition{Keep_remainder: true}, + }) + attrs.Srcs = partitionedSrcs["py"] + + if !partitionedSrcs["proto"].IsEmpty() { + protoInfo, _ := android.Bp2buildProtoProperties(ctx, &m.ModuleBase, partitionedSrcs["proto"]) + protoLabel := bazel.Label{Label: ":" + protoInfo.Name} + + pyProtoLibraryName := m.Name() + "_py_proto" + ctx.CreateBazelTargetModule(bazel.BazelTargetModuleProperties{ + Rule_class: "py_proto_library", + Bzl_load_location: "//build/bazel/rules/python:py_proto.bzl", + }, android.CommonAttributes{ + Name: pyProtoLibraryName, + }, &bazelPythonProtoLibraryAttributes{ + Deps: bazel.MakeSingleLabelListAttribute(protoLabel), + }) + + attrs.Deps.Add(bazel.MakeLabelAttribute(":" + pyProtoLibraryName)) + } + + // Bazel normally requires `import path.from.top.of.tree` statements in + // python code, but with soong you can directly import modules from libraries. + // Add "imports" attributes to the bazel library so it matches soong's behavior. + imports := "." + if m.properties.Pkg_path != nil { + // TODO(b/215119317) This is a hack to handle the fact that we don't convert + // pkg_path properly right now. If the folder structure that contains this + // Android.bp file matches pkg_path, we can set imports to an appropriate + // number of ../..s to emulate moving the files under a pkg_path folder. + pkg_path := filepath.Clean(*m.properties.Pkg_path) + if strings.HasPrefix(pkg_path, "/") { + ctx.ModuleErrorf("pkg_path cannot start with a /: %s", pkg_path) + } + + if !strings.HasSuffix(ctx.ModuleDir(), "/"+pkg_path) && ctx.ModuleDir() != pkg_path { + ctx.ModuleErrorf("Currently, bp2build only supports pkg_paths that are the same as the folders the Android.bp file is in. pkg_path: %s, module directory: %s", pkg_path, ctx.ModuleDir()) + } + numFolders := strings.Count(pkg_path, "/") + 1 + dots := make([]string, numFolders) + for i := 0; i < numFolders; i++ { + dots[i] = ".." + } + imports = strings.Join(dots, "/") + } + attrs.Imports = bazel.MakeStringListAttribute([]string{imports}) + return attrs } @@ -296,10 +347,6 @@ var ( protoExt = ".proto" pyVersion2 = "PY2" pyVersion3 = "PY3" - initFileName = "__init__.py" - mainFileName = "__main__.py" - entryPointFile = "entry_point.txt" - parFileExt = ".zip" internalPath = "internal" ) @@ -387,9 +434,9 @@ func (p *Module) anySrcHasExt(ctx android.BottomUpMutatorContext, ext string) bo } // DepsMutator mutates dependencies for this module: -// * handles proto dependencies, -// * if required, specifies launcher and adds launcher dependencies, -// * applies python version mutations to Python dependencies +// - handles proto dependencies, +// - if required, specifies launcher and adds launcher dependencies, +// - applies python version mutations to Python dependencies func (p *Module) DepsMutator(ctx android.BottomUpMutatorContext) { android.ProtoDeps(ctx, &p.protoProperties) @@ -621,8 +668,22 @@ func (p *Module) createSrcsZip(ctx android.ModuleContext, pkgPath string) androi protoFlags := android.GetProtoFlags(ctx, &p.protoProperties) protoFlags.OutTypeFlag = "--python_out" + if pkgPath != "" { + pkgPathStagingDir := android.PathForModuleGen(ctx, "protos_staged_for_pkg_path") + rule := android.NewRuleBuilder(pctx, ctx) + var stagedProtoSrcs android.Paths + for _, srcFile := range protoSrcs { + stagedProtoSrc := pkgPathStagingDir.Join(ctx, pkgPath, srcFile.Rel()) + rule.Command().Text("mkdir -p").Flag(filepath.Base(stagedProtoSrc.String())) + rule.Command().Text("cp -f").Input(srcFile).Output(stagedProtoSrc) + stagedProtoSrcs = append(stagedProtoSrcs, stagedProtoSrc) + } + rule.Build("stage_protos_for_pkg_path", "Stage protos for pkg_path") + protoSrcs = stagedProtoSrcs + } + for _, srcFile := range protoSrcs { - zip := genProto(ctx, srcFile, protoFlags, pkgPath) + zip := genProto(ctx, srcFile, protoFlags) zips = append(zips, zip) } } @@ -631,7 +692,8 @@ func (p *Module) createSrcsZip(ctx android.ModuleContext, pkgPath string) androi // in order to keep stable order of soong_zip params, we sort the keys here. roots := android.SortedStringKeys(relativeRootMap) - parArgs := []string{} + // Use -symlinks=false so that the symlinks in the bazel output directory are followed + parArgs := []string{"-symlinks=false"} if pkgPath != "" { // use package path as path prefix parArgs = append(parArgs, `-P `+pkgPath) diff --git a/python/python_test.go b/python/python_test.go index f57f504d7..42a1ffb2c 100644 --- a/python/python_test.go +++ b/python/python_test.go @@ -300,8 +300,6 @@ var ( filepath.Join("dir", "file2.py"): nil, filepath.Join("dir", "bin.py"): nil, filepath.Join("dir", "file4.py"): nil, - StubTemplateHost: []byte(`PYTHON_BINARY = '%interpreter%' - MAIN_FILE = '%main%'`), }, expectedBinaries: []pyModule{ { diff --git a/python/scripts/main_non_embedded.py b/python/scripts/main_non_embedded.py new file mode 100644 index 000000000..ffbaaa8db --- /dev/null +++ b/python/scripts/main_non_embedded.py @@ -0,0 +1,6 @@ +import runpy + +# The purpose of this file is to implement python 3.11+'s +# PYTHON_SAFE_PATH / -P option on older python versions. + +runpy._run_module_as_main("ENTRY_POINT", alter_argv=False) diff --git a/python/scripts/stub_template_host.txt b/python/scripts/stub_template_host.txt index 138404bf3..5eedc180c 100644 --- a/python/scripts/stub_template_host.txt +++ b/python/scripts/stub_template_host.txt @@ -1,7 +1,6 @@ #!/usr/bin/env '%interpreter%' import os -import re import tempfile import shutil import sys @@ -15,56 +14,22 @@ PYTHON_PATH = 'PYTHONPATH' # Don't imply 'import site' on initialization PYTHON_ARG = '-S' -def SearchPathEnv(name): - search_path = os.getenv('PATH', os.defpath).split(os.pathsep) - for directory in search_path: - if directory == '': continue - path = os.path.join(directory, name) - # Check if path is actual executable file. - if os.path.isfile(path) and os.access(path, os.X_OK): - return path - return None - -def FindPythonBinary(): - if PYTHON_BINARY.startswith('/'): - # Case 1: Python interpreter is directly provided with absolute path. - return PYTHON_BINARY - else: - # Case 2: Find Python interpreter through environment variable: PATH. - return SearchPathEnv(PYTHON_BINARY) - -# Create the runfiles tree by extracting the zip file -def ExtractRunfiles(): - temp_dir = tempfile.mkdtemp("", "Soong.python_") - zf = zipfile.ZipFile(os.path.dirname(__file__)) - zf.extractall(temp_dir) - return temp_dir - def Main(): args = sys.argv[1:] - new_env = {} - runfiles_path = None - + runfiles_path = tempfile.mkdtemp(prefix="Soong.python_") try: - runfiles_path = ExtractRunfiles() - - # Add runfiles path to PYTHONPATH. - python_path_entries = [runfiles_path] - - # Add top dirs within runfiles path to PYTHONPATH. - top_entries = [os.path.join(runfiles_path, i) for i in os.listdir(runfiles_path)] - top_pkg_dirs = [i for i in top_entries if os.path.isdir(i)] - python_path_entries += top_pkg_dirs + zf = zipfile.ZipFile(os.path.dirname(__file__)) + zf.extractall(runfiles_path) + zf.close() + new_python_path = runfiles_path old_python_path = os.environ.get(PYTHON_PATH) - separator = ':' - new_python_path = separator.join(python_path_entries) - # Copy old PYTHONPATH. if old_python_path: - new_python_path += separator + old_python_path - new_env[PYTHON_PATH] = new_python_path + os.environ.update({PYTHON_PATH: new_python_path + ":" + old_python_path}) + else: + os.environ.update({PYTHON_PATH: new_python_path}) # Now look for main python source file. main_filepath = os.path.join(runfiles_path, MAIN_FILE) @@ -73,21 +38,14 @@ def Main(): assert os.access(main_filepath, os.R_OK), \ 'Cannot exec() %r: file not readable.' % main_filepath - python_program = FindPythonBinary() - if python_program is None: - raise AssertionError('Could not find python binary: ' + PYTHON_BINARY) - args = [python_program, PYTHON_ARG, main_filepath] + args - - os.environ.update(new_env) + args = [PYTHON_BINARY, PYTHON_ARG, main_filepath] + args sys.stdout.flush() - retCode = subprocess.call(args) - sys.exit(retCode) - except: - raise + # close_fds=False so that you can run binaries with files provided on the command line: + # my_python_app --file <(echo foo) + sys.exit(subprocess.call(args, close_fds=False)) finally: - if runfiles_path is not None: - shutil.rmtree(runfiles_path, True) + shutil.rmtree(runfiles_path, ignore_errors=True) if __name__ == '__main__': Main() diff --git a/python/test.go b/python/test.go index 7413782cb..b9b346549 100644 --- a/python/test.go +++ b/python/test.go @@ -32,12 +32,6 @@ func registerPythonTestComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("python_test", PythonTestFactory) } -// Test option struct. -type TestOptions struct { - // If the test is a hostside(no device required) unittest that shall be run during presubmit check. - Unit_test *bool -} - type TestProperties struct { // the name of the test configuration (for example "AndroidTest.xml") that should be // installed with the module. @@ -55,7 +49,7 @@ type TestProperties struct { Java_data []string // Test options. - Test_options TestOptions + Test_options android.CommonTestOptions } type testDecorator struct { diff --git a/python/tests/dont_import_folder_of_entrypoint/Android.bp b/python/tests/dont_import_folder_of_entrypoint/Android.bp new file mode 100644 index 000000000..e54e9b2c0 --- /dev/null +++ b/python/tests/dont_import_folder_of_entrypoint/Android.bp @@ -0,0 +1,26 @@ +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +python_test_host { + name: "py_dont_import_folder_of_entrypoint_test", + main: "mypkg/main.py", + srcs: [ + "mypkg/main.py", + "mypkg/mymodule.py", + ], +} + +python_test_host { + name: "py_dont_import_folder_of_entrypoint_test_embedded_launcher", + main: "mypkg/main.py", + srcs: [ + "mypkg/main.py", + "mypkg/mymodule.py", + ], + version: { + py3: { + embedded_launcher: true, + }, + }, +} diff --git a/python/tests/dont_import_folder_of_entrypoint/mypkg/main.py b/python/tests/dont_import_folder_of_entrypoint/mypkg/main.py new file mode 100644 index 000000000..c6a36edfb --- /dev/null +++ b/python/tests/dont_import_folder_of_entrypoint/mypkg/main.py @@ -0,0 +1,15 @@ +import unittest +import sys + +class TestProtoWithPkgPath(unittest.TestCase): + + def test_cant_import_mymodule_directly(self): + with self.assertRaises(ImportError): + import mymodule + + def test_can_import_mymodule_by_parent_package(self): + import mypkg.mymodule + + +if __name__ == '__main__': + unittest.main() diff --git a/python/tests/dont_import_folder_of_entrypoint/mypkg/mymodule.py b/python/tests/dont_import_folder_of_entrypoint/mypkg/mymodule.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/python/tests/dont_import_folder_of_entrypoint/mypkg/mymodule.py diff --git a/python/tests/proto_pkg_path/Android.bp b/python/tests/proto_pkg_path/Android.bp new file mode 100644 index 000000000..a6bfd3f61 --- /dev/null +++ b/python/tests/proto_pkg_path/Android.bp @@ -0,0 +1,16 @@ +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +python_test_host { + name: "py_proto_pkg_path_test", + main: "main.py", + srcs: [ + "main.py", + "proto/*.proto", + ], + pkg_path: "mylib/subpackage", + proto: { + canonical_path_from_root: false, + }, +} diff --git a/python/tests/proto_pkg_path/main.py b/python/tests/proto_pkg_path/main.py new file mode 100644 index 000000000..c4acddef5 --- /dev/null +++ b/python/tests/proto_pkg_path/main.py @@ -0,0 +1,18 @@ +import sys + +import unittest +import mylib.subpackage.proto.test_pb2 as test_pb2 +import mylib.subpackage.proto.common_pb2 as common_pb2 + +print(sys.path) + +class TestProtoWithPkgPath(unittest.TestCase): + + def test_main(self): + x = test_pb2.MyMessage(name="foo", + common = common_pb2.MyCommonMessage(common="common")) + self.assertEqual(x.name, "foo") + self.assertEqual(x.common.common, "common") + +if __name__ == '__main__': + unittest.main() diff --git a/python/tests/proto_pkg_path/proto/common.proto b/python/tests/proto_pkg_path/proto/common.proto new file mode 100644 index 000000000..b24b8eaa5 --- /dev/null +++ b/python/tests/proto_pkg_path/proto/common.proto @@ -0,0 +1,5 @@ +syntax = "proto3"; + +message MyCommonMessage { + string common = 1; +} diff --git a/python/tests/proto_pkg_path/proto/test.proto b/python/tests/proto_pkg_path/proto/test.proto new file mode 100644 index 000000000..55f3b17c7 --- /dev/null +++ b/python/tests/proto_pkg_path/proto/test.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; + +import "mylib/subpackage/proto/common.proto"; + +message MyMessage { + string name = 1; + MyCommonMessage common = 2; +} diff --git a/python/tests/top_level_dirs/Android.bp b/python/tests/top_level_dirs/Android.bp new file mode 100644 index 000000000..574350ac9 --- /dev/null +++ b/python/tests/top_level_dirs/Android.bp @@ -0,0 +1,12 @@ +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +python_test_host { + name: "py_dont_add_top_level_dirs_test", + main: "main.py", + srcs: [ + "main.py", + "mypkg/mymodule.py", + ], +} diff --git a/python/tests/top_level_dirs/main.py b/python/tests/top_level_dirs/main.py new file mode 100644 index 000000000..9f30bfa01 --- /dev/null +++ b/python/tests/top_level_dirs/main.py @@ -0,0 +1,17 @@ +import unittest +import sys + +print(sys.path, file=sys.stderr) + +class TestProtoWithPkgPath(unittest.TestCase): + + def test_cant_import_mymodule_directly(self): + with self.assertRaises(ImportError): + import mymodule + + def test_can_import_mymodule_by_parent_package(self): + import mypkg.mymodule + + +if __name__ == '__main__': + unittest.main() diff --git a/python/tests/top_level_dirs/mypkg/mymodule.py b/python/tests/top_level_dirs/mypkg/mymodule.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/python/tests/top_level_dirs/mypkg/mymodule.py |