Ensure uniquely generated import aliases are not name mangled (python.org/dev/peps/pep-0008/#id34)

This commit is contained in:
boukeversteegh 2020-06-09 22:54:52 +02:00
parent 76db2f153e
commit 1a95a7988e
6 changed files with 58 additions and 32 deletions

View File

@ -129,7 +129,8 @@ def import_ancestor(current_package, imports, py_package, py_type):
distance_up = len(current_package) - len(py_package) distance_up = len(current_package) - len(py_package)
if py_package: if py_package:
string_import = py_package[-1] string_import = py_package[-1]
string_alias = f"__{'_' * distance_up}{string_import}" # Add trailing __ to avoid name mangling (python.org/dev/peps/pep-0008/#id34)
string_alias = f"_{'_' * distance_up}{string_import}__"
string_from = f"..{'.' * distance_up}" string_from = f"..{'.' * distance_up}"
imports.add(f"from {string_from} import {string_import} as {string_alias}") imports.add(f"from {string_from} import {string_import} as {string_alias}")
return f"{string_alias}.{py_type}" return f"{string_alias}.{py_type}"
@ -152,8 +153,9 @@ def import_cousin(current_package, imports, py_package, py_type):
py_package[len(shared_ancestry) : -1] py_package[len(shared_ancestry) : -1]
) )
string_import = py_package[-1] string_import = py_package[-1]
alias = f"{'_' * distance_up}" + safe_snake_case( # Add trailing __ to avoid name mangling (python.org/dev/peps/pep-0008/#id34)
string_alias = f"{'_' * distance_up}" + safe_snake_case(
".".join(py_package[len(shared_ancestry) :]) ".".join(py_package[len(shared_ancestry) :])
) ) + "__"
imports.add(f"from {string_from} import {string_import} as {alias}") imports.add(f"from {string_from} import {string_import} as {string_alias}")
return f"{alias}.{py_type}" return f"{string_alias}.{py_type}"

View File

@ -1,6 +1,4 @@
from betterproto.tests.output_betterproto.casing_message_field_uppercase.casing_message_field_uppercase import ( from betterproto.tests.output_betterproto.casing_message_field_uppercase import Test
Test,
)
def test_message_casing(): def test_message_casing():

View File

@ -10,9 +10,9 @@ message Test {
Nested nested = 1; Nested nested = 1;
Sibling sibling = 2; Sibling sibling = 2;
// Sibling sibling2 = 3; Sibling sibling2 = 3;
} }
message Sibling { message Sibling {
int32 foo = 1; int32 foo = 1;
} }

View File

@ -0,0 +1,19 @@
syntax = "proto3";
import "package.proto";
message Game {
message Player {
enum Race {
human = 0;
orc = 1;
}
}
}
message Test {
Game game = 1;
Game.Player GamePlayer = 2;
Game.Player.Race GamePlayerRace = 3;
equipment.Weapon Weapon = 4;
}

View File

@ -0,0 +1,7 @@
syntax = "proto3";
package equipment;
message Weapon {
}

View File

@ -174,8 +174,8 @@ def test_import_parent_package_from_child():
package="package.child", imports=imports, source_type="package.Message" package="package.child", imports=imports, source_type="package.Message"
) )
assert imports == {"from ... import package as ___package"} assert imports == {"from ... import package as __package__"}
assert name == "___package.Message" assert name == "__package__.Message"
def test_import_parent_package_from_deeply_nested_child(): def test_import_parent_package_from_deeply_nested_child():
@ -186,8 +186,8 @@ def test_import_parent_package_from_deeply_nested_child():
source_type="package.deeply.nested.Message", source_type="package.deeply.nested.Message",
) )
assert imports == {"from ... import nested as ___nested"} assert imports == {"from ... import nested as __nested__"}
assert name == "___nested.Message" assert name == "__nested__.Message"
def test_import_ancestor_package_from_nested_child(): def test_import_ancestor_package_from_nested_child():
@ -198,8 +198,8 @@ def test_import_ancestor_package_from_nested_child():
source_type="package.ancestor.Message", source_type="package.ancestor.Message",
) )
assert imports == {"from .... import ancestor as ____ancestor"} assert imports == {"from .... import ancestor as ___ancestor__"}
assert name == "____ancestor.Message" assert name == "___ancestor__.Message"
def test_import_root_package_from_child(): def test_import_root_package_from_child():
@ -224,16 +224,16 @@ def test_import_unrelated_package():
imports = set() imports = set()
name = get_ref_type(package="a", imports=imports, source_type="p.Message") name = get_ref_type(package="a", imports=imports, source_type="p.Message")
assert imports == {"from .. import p as _p"} assert imports == {"from .. import p as _p__"}
assert name == "_p.Message" assert name == "_p__.Message"
def test_import_unrelated_nested_package(): def test_import_unrelated_nested_package():
imports = set() imports = set()
name = get_ref_type(package="a.b", imports=imports, source_type="p.q.Message") name = get_ref_type(package="a.b", imports=imports, source_type="p.q.Message")
assert imports == {"from ...p import q as __p_q"} assert imports == {"from ...p import q as __p_q__"}
assert name == "__p_q.Message" assert name == "__p_q__.Message"
def test_import_unrelated_deeply_nested_package(): def test_import_unrelated_deeply_nested_package():
@ -242,16 +242,16 @@ def test_import_unrelated_deeply_nested_package():
package="a.b.c.d", imports=imports, source_type="p.q.r.s.Message" package="a.b.c.d", imports=imports, source_type="p.q.r.s.Message"
) )
assert imports == {"from .....p.q.r import s as ____p_q_r_s"} assert imports == {"from .....p.q.r import s as ____p_q_r_s__"}
assert name == "____p_q_r_s.Message" assert name == "____p_q_r_s__.Message"
def test_import_cousin_package(): def test_import_cousin_package():
imports = set() imports = set()
name = get_ref_type(package="a.x", imports=imports, source_type="a.y.Message") name = get_ref_type(package="a.x", imports=imports, source_type="a.y.Message")
assert imports == {"from .. import y as _y"} assert imports == {"from .. import y as _y__"}
assert name == "_y.Message" assert name == "_y__.Message"
def test_import_cousin_package_different_name(): def test_import_cousin_package_different_name():
@ -260,8 +260,8 @@ def test_import_cousin_package_different_name():
package="test.package1", imports=imports, source_type="cousin.package2.Message" package="test.package1", imports=imports, source_type="cousin.package2.Message"
) )
assert imports == {"from ...cousin import package2 as __cousin_package2"} assert imports == {"from ...cousin import package2 as __cousin_package2__"}
assert name == "__cousin_package2.Message" assert name == "__cousin_package2__.Message"
def test_import_cousin_package_same_name(): def test_import_cousin_package_same_name():
@ -270,16 +270,16 @@ def test_import_cousin_package_same_name():
package="test.package", imports=imports, source_type="cousin.package.Message" package="test.package", imports=imports, source_type="cousin.package.Message"
) )
assert imports == {"from ...cousin import package as __cousin_package"} assert imports == {"from ...cousin import package as __cousin_package__"}
assert name == "__cousin_package.Message" assert name == "__cousin_package__.Message"
def test_import_far_cousin_package(): def test_import_far_cousin_package():
imports = set() imports = set()
name = get_ref_type(package="a.x.y", imports=imports, source_type="a.b.c.Message") name = get_ref_type(package="a.x.y", imports=imports, source_type="a.b.c.Message")
assert imports == {"from ...b import c as __b_c"} assert imports == {"from ...b import c as __b_c__"}
assert name == "__b_c.Message" assert name == "__b_c__.Message"
def test_import_far_far_cousin_package(): def test_import_far_far_cousin_package():
@ -288,8 +288,8 @@ def test_import_far_far_cousin_package():
package="a.x.y.z", imports=imports, source_type="a.b.c.d.Message" package="a.x.y.z", imports=imports, source_type="a.b.c.d.Message"
) )
assert imports == {"from ....b.c import d as ___b_c_d"} assert imports == {"from ....b.c import d as ___b_c_d__"}
assert name == "___b_c_d.Message" assert name == "___b_c_d__.Message"
@pytest.mark.parametrize( @pytest.mark.parametrize(