Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
This repository was archived by the owner on Jul 22, 2023. It is now read-only.
/pythonnetPublic archive
forked frompythonnet/pythonnet

Commit467d1fd

Browse files
committed
allow excluding public .NET types from being exposed to Python
Introduced PyExportAttribute and handling for it in AssemblyManager
1 parent72fae73 commit467d1fd

File tree

9 files changed

+76
-17
lines changed

9 files changed

+76
-17
lines changed

‎CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
1313
- Added function that sets Py_NoSiteFlag to 1.
1414
- Added support for Jetson Nano.
1515
- Added support for__len__ for .NET classes that implement ICollection
16+
- Added`PyExport` attribute to hide .NET types from Python
1617
- Added PythonException.Format method to format exceptions the same as traceback.format_exception
1718
- Added Runtime.None to be able to pass None as parameter into Python from .NET
1819
- Added PyObject.IsNone() to check if a Python object is None in .NET.

‎setup.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,7 @@ def build_extension(self, ext):
306306
_config="{0}Win".format(CONFIG)
307307
_solution_file="pythonnet.sln"
308308
_custom_define_constants=False
309+
defines.append("NET40")
309310
elifDEVTOOLS=="MsDev15":
310311
_xbuild='"{0}"'.format(self._find_msbuild_tool_15())
311312
_config="{0}Win".format(CONFIG)
@@ -316,6 +317,7 @@ def build_extension(self, ext):
316317
_config="{0}Mono".format(CONFIG)
317318
_solution_file="pythonnet.sln"
318319
_custom_define_constants=False
320+
defines.append("NET40")
319321
elifDEVTOOLS=="dotnet":
320322
_xbuild="dotnet msbuild"
321323
_config="{0}Mono".format(CONFIG)

‎src/runtime/PyExportAttribute.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
namespacePython.Runtime{
2+
usingSystem;
3+
4+
/// <summary>
5+
/// Controls visibility to Python for public .NET type or an entire assembly
6+
/// </summary>
7+
[AttributeUsage(AttributeTargets.Class|AttributeTargets.Delegate|AttributeTargets.Enum
8+
|AttributeTargets.Interface|AttributeTargets.Struct|AttributeTargets.Assembly,
9+
AllowMultiple=false,
10+
Inherited=false)]
11+
publicclassPyExportAttribute:Attribute
12+
{
13+
internalreadonlyboolExport;
14+
publicPyExportAttribute(boolexport){this.Export=export;}
15+
}
16+
}

‎src/runtime/Python.Runtime.csproj

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,46 +29,46 @@
2929
<PlatformTarget>x64</PlatformTarget>
3030
</PropertyGroup>-->
3131
<PropertyGroupCondition=" '$(Configuration)' == 'ReleaseMono'">
32-
<DefineConstantsCondition="'$(DefineConstants)' == ''">PYTHON2;PYTHON27;UCS4</DefineConstants>
32+
<DefineConstantsCondition="'$(DefineConstants)' == ''">NET40;PYTHON2;PYTHON27;UCS4</DefineConstants>
3333
<Optimize>true</Optimize>
3434
<DebugType>pdbonly</DebugType>
3535
</PropertyGroup>
3636
<PropertyGroupCondition=" '$(Configuration)' == 'ReleaseMonoPY3'">
37-
<DefineConstantsCondition="'$(DefineConstants)' == ''">PYTHON3;PYTHON38;UCS4</DefineConstants>
37+
<DefineConstantsCondition="'$(DefineConstants)' == ''">NET40;PYTHON3;PYTHON38;UCS4</DefineConstants>
3838
<Optimize>true</Optimize>
3939
<DebugType>pdbonly</DebugType>
4040
</PropertyGroup>
4141
<PropertyGroupCondition=" '$(Configuration)' == 'DebugMono'">
4242
<DebugSymbols>true</DebugSymbols>
43-
<DefineConstantsCondition="'$(DefineConstants)' == ''">PYTHON2;PYTHON27;UCS4;TRACE;DEBUG</DefineConstants>
43+
<DefineConstantsCondition="'$(DefineConstants)' == ''">NET40;PYTHON2;PYTHON27;UCS4;TRACE;DEBUG</DefineConstants>
4444
<Optimize>false</Optimize>
4545
<DebugType>full</DebugType>
4646
</PropertyGroup>
4747
<PropertyGroupCondition=" '$(Configuration)' == 'DebugMonoPY3'">
4848
<DebugSymbols>true</DebugSymbols>
49-
<DefineConstantsCondition="'$(DefineConstants)' == ''">PYTHON3;PYTHON38;UCS4;TRACE;DEBUG</DefineConstants>
49+
<DefineConstantsCondition="'$(DefineConstants)' == ''">NET40;PYTHON3;PYTHON38;UCS4;TRACE;DEBUG</DefineConstants>
5050
<Optimize>false</Optimize>
5151
<DebugType>full</DebugType>
5252
</PropertyGroup>
5353
<PropertyGroupCondition=" '$(Configuration)' == 'ReleaseWin'">
54-
<DefineConstantsCondition="'$(DefineConstants)' == ''">PYTHON2;PYTHON27;UCS2</DefineConstants>
54+
<DefineConstantsCondition="'$(DefineConstants)' == ''">NET40;PYTHON2;PYTHON27;UCS2</DefineConstants>
5555
<Optimize>true</Optimize>
5656
<DebugType>pdbonly</DebugType>
5757
</PropertyGroup>
5858
<PropertyGroupCondition=" '$(Configuration)' == 'ReleaseWinPY3'">
59-
<DefineConstantsCondition="'$(DefineConstants)' == ''">PYTHON3;PYTHON38;UCS2</DefineConstants>
59+
<DefineConstantsCondition="'$(DefineConstants)' == ''">NET40;PYTHON3;PYTHON38;UCS2</DefineConstants>
6060
<Optimize>true</Optimize>
6161
<DebugType>pdbonly</DebugType>
6262
</PropertyGroup>
6363
<PropertyGroupCondition=" '$(Configuration)' == 'DebugWin'">
6464
<DebugSymbols>true</DebugSymbols>
65-
<DefineConstantsCondition="'$(DefineConstants)' == ''">PYTHON2;PYTHON27;UCS2;TRACE;DEBUG</DefineConstants>
65+
<DefineConstantsCondition="'$(DefineConstants)' == ''">NET40;PYTHON2;PYTHON27;UCS2;TRACE;DEBUG</DefineConstants>
6666
<Optimize>false</Optimize>
6767
<DebugType>full</DebugType>
6868
</PropertyGroup>
6969
<PropertyGroupCondition=" '$(Configuration)' == 'DebugWinPY3'">
7070
<DebugSymbols>true</DebugSymbols>
71-
<DefineConstantsCondition="'$(DefineConstants)' == ''">PYTHON3;PYTHON38;UCS2;TRACE;DEBUG</DefineConstants>
71+
<DefineConstantsCondition="'$(DefineConstants)' == ''">NET40;PYTHON3;PYTHON38;UCS2;TRACE;DEBUG</DefineConstants>
7272
<Optimize>false</Optimize>
7373
<DebugType>full</DebugType>
7474
</PropertyGroup>
@@ -131,6 +131,7 @@
131131
<CompileInclude="propertyobject.cs" />
132132
<CompileInclude="pyansistring.cs" />
133133
<CompileInclude="pydict.cs" />
134+
<CompileInclude="PyExportAttribute.cs" />
134135
<CompileInclude="pyfloat.cs" />
135136
<CompileInclude="pyint.cs" />
136137
<CompileInclude="pyiter.cs" />
@@ -151,6 +152,7 @@
151152
<CompileInclude="Util.cs" />
152153
<CompileInclude="platform\Types.cs" />
153154
<CompileInclude="platform\LibraryLoader.cs" />
155+
<CompileInclude="polyfill\ReflectionPolifills.cs" />
154156
<CompileInclude="slots\mp_length.cs" />
155157
</ItemGroup>
156158
<ItemGroupCondition=" '$(PythonInteropFile)' != ''">

‎src/runtime/assemblymanager.cs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,10 @@ public static bool LoadImplicit(string name, bool warn = true)
346346
/// </summary>
347347
internalstaticvoidScanAssembly(Assemblyassembly)
348348
{
349+
if(assembly.GetCustomAttribute<PyExportAttribute>()?.Export==false)
350+
{
351+
return;
352+
}
349353
// A couple of things we want to do here: first, we want to
350354
// gather a list of all of the namespaces contributed to by
351355
// the assembly.
@@ -458,7 +462,7 @@ public static Type LookupType(string qname)
458462
foreach(Assemblyassemblyinassemblies)
459463
{
460464
Typetype=assembly.GetType(qname);
461-
if(type!=null)
465+
if(type!=null&&IsExported(type))
462466
{
463467
returntype;
464468
}
@@ -472,33 +476,35 @@ public static Type LookupType(string qname)
472476
/// type.
473477
/// </summary>
474478
publicstaticIEnumerable<Type>LookupTypes(stringqualifiedName)
475-
=>assemblies.Select(assembly=>assembly.GetType(qualifiedName)).Where(type=>type!=null);
479+
=>assemblies.Select(assembly=>assembly.GetType(qualifiedName)).Where(type=>type!=null&&IsExported(type));
476480

477481
internalstaticType[]GetTypes(Assemblya)
478482
{
479483
if(a.IsDynamic)
480484
{
481485
try
482486
{
483-
returna.GetTypes();
487+
returna.GetTypes().Where(IsExported).ToArray();
484488
}
485489
catch(ReflectionTypeLoadExceptionexc)
486490
{
487491
// Return all types that were successfully loaded
488-
returnexc.Types.Where(x=>x!=null).ToArray();
492+
returnexc.Types.Where(x=>x!=null&&IsExported(x)).ToArray();
489493
}
490494
}
491495
else
492496
{
493497
try
494498
{
495-
returna.GetExportedTypes();
499+
returna.GetExportedTypes().Where(IsExported).ToArray();
496500
}
497501
catch(FileNotFoundException)
498502
{
499503
returnnewType[0];
500504
}
501505
}
502506
}
507+
508+
staticboolIsExported(Typetype)=>type.GetCustomAttribute<PyExportAttribute>()?.Export!=false;
503509
}
504510
}
Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
usingSystem;
2+
usingSystem.Linq;
23
usingSystem.Reflection;
34
usingSystem.Reflection.Emit;
45

56
namespacePython.Runtime
67
{
7-
#ifNETSTANDARD
8+
[Obsolete("This API is for internal use only")]
89
publicstaticclassReflectionPolifills
910
{
11+
#ifNETSTANDARD
1012
publicstaticAssemblyBuilderDefineDynamicAssembly(thisAppDomainappDomain,AssemblyNameassemblyName,AssemblyBuilderAccessassemblyBuilderAccess)
1113
{
1214
returnAssemblyBuilder.DefineDynamicAssembly(assemblyName,assemblyBuilderAccess);
@@ -16,6 +18,21 @@ public static Type CreateType(this TypeBuilder typeBuilder)
1618
{
1719
returntypeBuilder.GetTypeInfo().GetType();
1820
}
19-
}
2021
#endif
22+
#ifNET40
23+
publicstaticTGetCustomAttribute<T>(thisTypetype)whereT:Attribute
24+
{
25+
returntype.GetCustomAttributes(typeof(T),inherit:false)
26+
.Cast<T>()
27+
.SingleOrDefault();
28+
}
29+
30+
publicstaticTGetCustomAttribute<T>(thisAssemblyassembly)whereT:Attribute
31+
{
32+
returnassembly.GetCustomAttributes(typeof(T),inherit:false)
33+
.Cast<T>()
34+
.SingleOrDefault();
35+
}
36+
#endif
37+
}
2138
}

‎src/testing/Python.Test.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
<CompileInclude="doctest.cs" />
9393
<CompileInclude="subclasstest.cs" />
9494
<CompileInclude="ReprTest.cs" />
95+
<CompileInclude="nonexportable.cs" />
9596
<CompileInclude="mp_lengthtest.cs" />
9697
</ItemGroup>
9798
<ItemGroup>

‎src/testing/nonexportable.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespacePython.Test
2+
{
3+
usingPython.Runtime;
4+
5+
// this class should not be visible to Python
6+
[PyExport(false)]
7+
publicclassNonExportable{}
8+
}

‎src/tests/test_class.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ def test_basic_reference_type():
1414
"""Test usage of CLR defined reference types."""
1515
assertSystem.String.Empty==""
1616

17-
1817
deftest_basic_value_type():
1918
"""Test usage of CLR defined value types."""
2019
assertSystem.Int32.MaxValue==2147483647
@@ -29,7 +28,6 @@ def test_class_standard_attrs():
2928
assertisinstance(ClassTest.__dict__,DictProxyType)
3029
assertlen(ClassTest.__doc__)>0
3130

32-
3331
deftest_class_docstrings():
3432
"""Test standard class docstring generation"""
3533
fromPython.TestimportClassTest
@@ -58,6 +56,14 @@ def test_non_public_class():
5856
withpytest.raises(AttributeError):
5957
_=Test.InternalClass
6058

59+
deftest_non_exported():
60+
"""Test [PyExport(false)]"""
61+
withpytest.raises(ImportError):
62+
fromPython.TestimportNonExportable
63+
64+
withpytest.raises(AttributeError):
65+
_=Test.NonExportable
66+
6167

6268
deftest_basic_subclass():
6369
"""Test basic subclass of a managed class."""

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp