Compare commits
2 Commits
2796ffd5f3
...
6ddd6389bd
Author | SHA1 | Date | |
---|---|---|---|
![]() |
6ddd6389bd | ||
![]() |
a210de14ff |
|
@ -84,7 +84,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<AdditionalIncludeDirectories>include;header;src\pch;..\ConceptCore\output\include;..\OfficeOLE\include;C:\Program Files (x86)\Python312-32\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>include;header;src\pch;..\GH-ConceptCore\output\include;..\OfficeOLE\include;C:\Program Files (x86)\Python312-32\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>POCO_STATIC; NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>POCO_STATIC; NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
<WarningLevel>Level4</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
@ -101,7 +101,7 @@
|
||||||
<BuildStlModules>false</BuildStlModules>
|
<BuildStlModules>false</BuildStlModules>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalLibraryDirectories>lib\x86;..\ConceptCore\output\lib\x86;..\OfficeOLE\output\lib\x86;C:\Program Files (x86)\Python312-32\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>lib\x86;..\GH-ConceptCore\output\lib\x86;..\OfficeOLE\output\lib\x86;C:\Program Files (x86)\Python312-32\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>Version.lib;OfficeOLE.lib;ConceptCoreLibrary.lib;RSlang.lib;cclGraph.lib;cclLang.lib;oldnames.lib;Htmlhelp.Lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>Version.lib;OfficeOLE.lib;ConceptCoreLibrary.lib;RSlang.lib;cclGraph.lib;cclLang.lib;oldnames.lib;Htmlhelp.Lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
@ -121,8 +121,7 @@
|
||||||
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
</ResourceCompile>
|
</ResourceCompile>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Command>xcopy /y /s /q /i "import\cctext\" "$(OutDir)\cctext"
|
<Command>xcopy /y /s /q /i "distr\app" "$(OutDir)"
|
||||||
xcopy /y /s /q /i "distr\app" "$(OutDir)"
|
|
||||||
copy "C:\Program Files (x86)\Python312-32\Python312.dll" "$(OutDir)"
|
copy "C:\Program Files (x86)\Python312-32\Python312.dll" "$(OutDir)"
|
||||||
copy "C:\Program Files (x86)\Python312-32\Python312.pdb" "$(OutDir)"
|
copy "C:\Program Files (x86)\Python312-32\Python312.pdb" "$(OutDir)"
|
||||||
if not exist bin\x86 mkdir bin\x86
|
if not exist bin\x86 mkdir bin\x86
|
||||||
|
@ -131,7 +130,7 @@ copy "$(OutDir)Exteor.exe" "bin\x86\Exteor.exe"</Command>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<AdditionalIncludeDirectories>include;header;src\pch;..\ConceptCore\output\include;..\OfficeOLE\include;C:\Program Files\Python312\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>include;header;src\pch;..\GH-ConceptCore\output\include;..\OfficeOLE\include;C:\Program Files\Python312\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>POCO_STATIC;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>POCO_STATIC;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
<WarningLevel>Level4</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
@ -148,7 +147,7 @@ copy "$(OutDir)Exteor.exe" "bin\x86\Exteor.exe"</Command>
|
||||||
<BuildStlModules>false</BuildStlModules>
|
<BuildStlModules>false</BuildStlModules>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalLibraryDirectories>lib\x64;..\ConceptCore\output\lib\x64;..\OfficeOLE\output\lib\x64;C:\Program Files\Python312\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>lib\x64;..\GH-ConceptCore\output\lib\x64;..\OfficeOLE\output\lib\x64;C:\Program Files\Python312\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>Version.lib;OfficeOLE.lib;ConceptCoreLibrary.lib;RSlang.lib;cclGraph.lib;cclLang.lib;oldnames.lib;Htmlhelp.Lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>Version.lib;OfficeOLE.lib;ConceptCoreLibrary.lib;RSlang.lib;cclGraph.lib;cclLang.lib;oldnames.lib;Htmlhelp.Lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
@ -168,8 +167,7 @@ copy "$(OutDir)Exteor.exe" "bin\x86\Exteor.exe"</Command>
|
||||||
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
</ResourceCompile>
|
</ResourceCompile>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Command>xcopy /y /s /q /i "import\cctext" "$(OutDir)\cctext\"
|
<Command>xcopy /y /s /q /i "distr\app" "$(OutDir)"
|
||||||
xcopy /y /s /q /i "distr\app" "$(OutDir)"
|
|
||||||
if not exist bin\x64 mkdir bin\x64
|
if not exist bin\x64 mkdir bin\x64
|
||||||
copy "$(OutDir)Exteor.exe" "bin\x64\Exteor.exe"</Command>
|
copy "$(OutDir)Exteor.exe" "bin\x64\Exteor.exe"</Command>
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
|
@ -182,7 +180,7 @@ copy "$(OutDir)Exteor.exe" "bin\x64\Exteor.exe"</Command>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>include;header;src\pch;..\ConceptCore\output\include;..\OfficeOLE\include;C:\Program Files (x86)\Python312-32\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>include;header;src\pch;..\GH-ConceptCore\output\include;..\OfficeOLE\include;C:\Program Files (x86)\Python312-32\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>POCO_STATIC;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>POCO_STATIC;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
||||||
<ObjectFileName>$(IntDir)obj\</ObjectFileName>
|
<ObjectFileName>$(IntDir)obj\</ObjectFileName>
|
||||||
|
@ -191,7 +189,7 @@ copy "$(OutDir)Exteor.exe" "bin\x64\Exteor.exe"</Command>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<AdditionalLibraryDirectories>lib\x86;..\ConceptCore\output\lib\x86;..\OfficeOLE\output\lib\x86;C:\Program Files (x86)\Python312-32\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>lib\x86;..\GH-ConceptCore\output\lib\x86;..\OfficeOLE\output\lib\x86;C:\Program Files (x86)\Python312-32\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>Version.lib;OfficeOLEd.lib;ConceptCoreLibraryd.lib;cclLangd.lib;RSlangd.lib;cclGraphd.lib;Htmlhelp.Lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>Version.lib;OfficeOLEd.lib;ConceptCoreLibraryd.lib;cclLangd.lib;RSlangd.lib;cclGraphd.lib;Htmlhelp.Lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||||
<ProgramDatabaseFile>$(OutDir)$(ProjectName).pdb</ProgramDatabaseFile>
|
<ProgramDatabaseFile>$(OutDir)$(ProjectName).pdb</ProgramDatabaseFile>
|
||||||
|
@ -211,8 +209,7 @@ copy "$(OutDir)Exteor.exe" "bin\x64\Exteor.exe"</Command>
|
||||||
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
</ResourceCompile>
|
</ResourceCompile>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Command>xcopy /y /s /q /i "import\cctext" "$(OutDir)\cctext\"
|
<Command>xcopy /y /s /q /i "distr\app" "$(OutDir)"
|
||||||
xcopy /y /s /q /i "distr\app" "$(OutDir)"
|
|
||||||
copy "C:\Program Files (x86)\Python312-32\Python312_d.dll" "$(OutDir)"
|
copy "C:\Program Files (x86)\Python312-32\Python312_d.dll" "$(OutDir)"
|
||||||
copy "C:\Program Files (x86)\Python312-32\Python312_d.pdb" "$(OutDir)"</Command>
|
copy "C:\Program Files (x86)\Python312-32\Python312_d.pdb" "$(OutDir)"</Command>
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
|
@ -229,7 +226,7 @@ copy "C:\Program Files (x86)\Python312-32\Python312_d.pdb" "$(OutDir)"</Command>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>include;header;src\pch;..\ConceptCore\output\include;..\OfficeOLE\include;C:\Program Files\Python312\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>include;header;src\pch;..\GH-ConceptCore\output\include;..\OfficeOLE\include;C:\Program Files\Python312\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>POCO_STATIC; _DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>POCO_STATIC; _DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
||||||
<ObjectFileName>$(IntDir)obj\</ObjectFileName>
|
<ObjectFileName>$(IntDir)obj\</ObjectFileName>
|
||||||
|
@ -238,7 +235,7 @@ copy "C:\Program Files (x86)\Python312-32\Python312_d.pdb" "$(OutDir)"</Command>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<AdditionalLibraryDirectories>lib\x64;..\ConceptCore\output\lib\x64;..\OfficeOLE\output\lib\x64;C:\Program Files\Python312\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>lib\x64;..\GH-ConceptCore\output\lib\x64;..\OfficeOLE\output\lib\x64;C:\Program Files\Python312\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>Version.lib;OfficeOLEd.lib;ConceptCoreLibraryd.lib;cclLangd.lib;RSlangd.lib;cclGraphd.lib;Htmlhelp.Lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>Version.lib;OfficeOLEd.lib;ConceptCoreLibraryd.lib;cclLangd.lib;RSlangd.lib;cclGraphd.lib;Htmlhelp.Lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||||
<ProgramDatabaseFile>$(OutDir)$(ProjectName).pdb</ProgramDatabaseFile>
|
<ProgramDatabaseFile>$(OutDir)$(ProjectName).pdb</ProgramDatabaseFile>
|
||||||
|
@ -257,8 +254,7 @@ copy "C:\Program Files (x86)\Python312-32\Python312_d.pdb" "$(OutDir)"</Command>
|
||||||
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
</ResourceCompile>
|
</ResourceCompile>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Command>xcopy /y /s /q /i "import\cctext" "$(OutDir)\cctext\"
|
<Command>xcopy /y /s /q /i "distr\app" "$(OutDir)"</Command>
|
||||||
xcopy /y /s /q /i "distr\app" "$(OutDir)"</Command>
|
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -437,7 +433,7 @@ xcopy /y /s /q /i "distr\app" "$(OutDir)"</Command>
|
||||||
<Text Include="Doc\Порядок выпуска версии.txt" />
|
<Text Include="Doc\Порядок выпуска версии.txt" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\ConceptCore\ccl\core\ConceptLibrary.vcxproj">
|
<ProjectReference Include="..\GH-ConceptCore\ccl\core\ConceptLibrary.vcxproj">
|
||||||
<Project>{b0aba27b-9d39-4b48-9977-aff20925b309}</Project>
|
<Project>{b0aba27b-9d39-4b48-9977-aff20925b309}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\OfficeOLE\OfficeOLE.vcxproj">
|
<ProjectReference Include="..\OfficeOLE\OfficeOLE.vcxproj">
|
||||||
|
|
|
@ -8,9 +8,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Exteor", "Exteor.vcxproj",
|
||||||
{B0ABA27B-9D39-4B48-9977-AFF20925B309} = {B0ABA27B-9D39-4B48-9977-AFF20925B309}
|
{B0ABA27B-9D39-4B48-9977-AFF20925B309} = {B0ABA27B-9D39-4B48-9977-AFF20925B309}
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ConceptCore", "..\ConceptCore\ccl\core\ConceptLibrary.vcxproj", "{B0ABA27B-9D39-4B48-9977-AFF20925B309}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ConceptCore", "..\GH-ConceptCore\ccl\core\ConceptLibrary.vcxproj", "{B0ABA27B-9D39-4B48-9977-AFF20925B309}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cclTest", "..\ConceptCore\ccl\core\test\cclTest.vcxproj", "{F87048D4-952A-460E-96E8-1E2E1EAE34FC}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cclTest", "..\GH-ConceptCore\ccl\core\test\cclTest.vcxproj", "{F87048D4-952A-460E-96E8-1E2E1EAE34FC}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XTRCoreTest", "test\XTRCoreTest.vcxproj", "{576D16B8-96BF-4B5A-8B09-E1916375E34F}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XTRCoreTest", "test\XTRCoreTest.vcxproj", "{576D16B8-96BF-4B5A-8B09-E1916375E34F}"
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
@ -18,19 +18,19 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XTRCoreTest", "test\XTRCore
|
||||||
{F87048D4-952A-460E-96E8-1E2E1EAE34FC} = {F87048D4-952A-460E-96E8-1E2E1EAE34FC}
|
{F87048D4-952A-460E-96E8-1E2E1EAE34FC} = {F87048D4-952A-460E-96E8-1E2E1EAE34FC}
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RSlang", "..\ConceptCore\ccl\rslang\RSlang.vcxproj", "{A8529C63-42F5-43E6-97B8-2EC83F23E1F9}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RSlang", "..\GH-ConceptCore\ccl\rslang\RSlang.vcxproj", "{A8529C63-42F5-43E6-97B8-2EC83F23E1F9}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RSLangTest", "..\ConceptCore\ccl\rslang\test\rslTest.vcxproj", "{32469CE1-303B-4DB4-8E03-B7EBED5851EB}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RSLangTest", "..\GH-ConceptCore\ccl\rslang\test\rslTest.vcxproj", "{32469CE1-303B-4DB4-8E03-B7EBED5851EB}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cclGraph", "..\ConceptCore\ccl\cclGraph\cclGraph.vcxproj", "{7E1D5338-F819-4C96-B461-9EAAB8D02E1D}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cclGraph", "..\GH-ConceptCore\ccl\cclGraph\cclGraph.vcxproj", "{7E1D5338-F819-4C96-B461-9EAAB8D02E1D}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cclGraphTest", "..\ConceptCore\ccl\cclGraph\test\cclGraphTest.vcxproj", "{5A2501C1-FEFB-4B14-A94D-E8F19ADEA239}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cclGraphTest", "..\GH-ConceptCore\ccl\cclGraph\test\cclGraphTest.vcxproj", "{5A2501C1-FEFB-4B14-A94D-E8F19ADEA239}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cclCommonsTest", "..\ConceptCore\ccl\cclCommons\test\cclCommonsTest.vcxproj", "{53A380CF-B599-4170-89B1-642F1C3772E1}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cclCommonsTest", "..\GH-ConceptCore\ccl\cclCommons\test\cclCommonsTest.vcxproj", "{53A380CF-B599-4170-89B1-642F1C3772E1}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cclLang", "..\ConceptCore\ccl\cclLang\cclLang.vcxproj", "{76B03803-56CC-47C2-A8F0-2241FCAF2898}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cclLang", "..\GH-ConceptCore\ccl\cclLang\cclLang.vcxproj", "{76B03803-56CC-47C2-A8F0-2241FCAF2898}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cclLangTest", "..\ConceptCore\ccl\cclLang\test\cclLangTest.vcxproj", "{4754356B-DC01-4564-A035-270FFB72F6A0}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cclLangTest", "..\GH-ConceptCore\ccl\cclLang\test\cclLangTest.vcxproj", "{4754356B-DC01-4564-A035-270FFB72F6A0}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "libs", "libs", "{DC591058-8A8A-460E-93D0-B57C848DF12B}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "libs", "libs", "{DC591058-8A8A-460E-93D0-B57C848DF12B}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
14.06.2024 Экстеор 4.9.3
|
||||||
|
• Грамматика: разрешено использование одного аргумента для мультифильтра - Fi1,2[X1*X1](S1)
|
||||||
|
• исправлена ошибка, приводившая к некорректному вычислению типизаций рекурсии с пустым множеством
|
||||||
|
• использование cctext без встраивания кода (через pip)
|
||||||
13.05.2024 Экстеор 4.9.2
|
13.05.2024 Экстеор 4.9.2
|
||||||
• Грамматика: разрешено использование пустого множества как литерала с типизацией B(R0)
|
• Грамматика: разрешено использование пустого множества как литерала с типизацией B(R0)
|
||||||
• Грамматика: разрешено объявление кортежем в императивных блоках
|
• Грамматика: разрешено объявление кортежем в императивных блоках
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
''' Concept core text processing library. '''
|
|
||||||
# pylint: skip-file
|
|
||||||
from .syntax import RuSyntax, Capitalization
|
|
||||||
from .rumodel import Morphology, SemanticRole, WordTag, morpho, split_grams, combine_grams
|
|
||||||
from .ruparser import PhraseParser, WordToken, Collation
|
|
||||||
from .reference import EntityReference, ReferenceType, SyntacticReference, parse_reference
|
|
||||||
from .context import TermForm, Entity, TermContext
|
|
||||||
from .resolver import Reference, Position, Resolver, ResolvedReference, resolve_entity, resolve_syntactic, extract_entities
|
|
||||||
|
|
||||||
from .conceptapi import (
|
|
||||||
parse, normalize,
|
|
||||||
generate_lexeme, inflect, inflect_context, inflect_substitute, inflect_dependant,
|
|
||||||
match_all_morpho, find_substr
|
|
||||||
)
|
|
||||||
|
|
||||||
# TODO: implement Part of speech transition for VERB <-> NOUN
|
|
|
@ -1,90 +0,0 @@
|
||||||
'''
|
|
||||||
Concept API Python functions.
|
|
||||||
|
|
||||||
::guarantee:: doesn't raise exceptions and returns workable outputs
|
|
||||||
'''
|
|
||||||
from cctext.rumodel import Morphology
|
|
||||||
from .syntax import RuSyntax
|
|
||||||
from .ruparser import PhraseParser
|
|
||||||
from .rumodel import split_grams
|
|
||||||
|
|
||||||
parser = PhraseParser()
|
|
||||||
|
|
||||||
|
|
||||||
def parse(text: str, require_grams: str = '') -> str:
|
|
||||||
''' Determine morpho tags for input text.
|
|
||||||
::returns:: string of comma separated grammar tags or empty string '''
|
|
||||||
model = parser.parse(text, require_grams=split_grams(require_grams))
|
|
||||||
if model is None:
|
|
||||||
return ''
|
|
||||||
result = model.get_morpho().to_text()
|
|
||||||
return result if result != 'UNKN' else ''
|
|
||||||
|
|
||||||
|
|
||||||
# def parse_variants(text: str, require_grams: str = '') -> list[tuple[str, str]]:
|
|
||||||
# ''' Get all variants of a parse.
|
|
||||||
# ::returns:: string of comma separated grammar tags or empty string '''
|
|
||||||
|
|
||||||
|
|
||||||
def generate_lexeme(text_normal: str) -> list[tuple[str, str]]:
|
|
||||||
''' Get all inflected forms belonging to same Lexeme. '''
|
|
||||||
model = parser.parse(text_normal)
|
|
||||||
if not model:
|
|
||||||
return []
|
|
||||||
result = []
|
|
||||||
for form in model.get_form().lexeme:
|
|
||||||
result.append((model.inflect(form.tag.grammemes), Morphology(form.tag).to_text()))
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def normalize(text: str) -> str:
|
|
||||||
''' Generate normal form.
|
|
||||||
::returns:: normal form of input text or text itself if no parse is available '''
|
|
||||||
model = parser.parse(text)
|
|
||||||
if model is None:
|
|
||||||
return text
|
|
||||||
return model.normal_form()
|
|
||||||
|
|
||||||
|
|
||||||
def inflect(text: str, target_grams: str) -> str:
|
|
||||||
''' Inflect text to match required tags.
|
|
||||||
::returns:: infected text or initial text if infection failed '''
|
|
||||||
target_set = split_grams(target_grams)
|
|
||||||
model = parser.parse(text)
|
|
||||||
if model is None:
|
|
||||||
return text
|
|
||||||
return model.inflect(target_set)
|
|
||||||
|
|
||||||
|
|
||||||
def inflect_context(target: str, before: str = '', after: str = '') -> str:
|
|
||||||
''' Inflect text in accordance to context before and after. '''
|
|
||||||
return parser.inflect_context(target, before, after)
|
|
||||||
|
|
||||||
|
|
||||||
def inflect_substitute(substitute_normal: str, original: str) -> str:
|
|
||||||
''' Inflect substitute to match original form. '''
|
|
||||||
return parser.inflect_substitute(substitute_normal, original)
|
|
||||||
|
|
||||||
|
|
||||||
def inflect_dependant(dependant_normal: str, master: str) -> str:
|
|
||||||
''' Inflect dependant to coordinate with master text. '''
|
|
||||||
return parser.inflect_dependant(dependant_normal, master)
|
|
||||||
|
|
||||||
|
|
||||||
def match_all_morpho(text: str, filter_grams: str) -> list[list[int]]:
|
|
||||||
''' Search for all words corresponding to tags. '''
|
|
||||||
target_set = split_grams(filter_grams)
|
|
||||||
if len(target_set) == 0:
|
|
||||||
return []
|
|
||||||
|
|
||||||
result = []
|
|
||||||
for elem in RuSyntax.tokenize(text):
|
|
||||||
model = parser.parse(elem.text, require_grams=target_set)
|
|
||||||
if model:
|
|
||||||
result.append([elem.start, elem.stop])
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def find_substr(text: str, sub: str) -> tuple[int, int]:
|
|
||||||
''' Search for substring position in text regardless of morphology. '''
|
|
||||||
return parser.find_substr(text, sub)
|
|
|
@ -1,84 +0,0 @@
|
||||||
''' Term context for reference resolution. '''
|
|
||||||
from typing import Iterable, Optional, TypedDict
|
|
||||||
|
|
||||||
from .ruparser import PhraseParser
|
|
||||||
from .rumodel import WordTag
|
|
||||||
|
|
||||||
|
|
||||||
parser = PhraseParser()
|
|
||||||
|
|
||||||
|
|
||||||
class TermForm(TypedDict):
|
|
||||||
''' Represents term in a specific form. '''
|
|
||||||
text: str
|
|
||||||
grams: Iterable[str]
|
|
||||||
|
|
||||||
|
|
||||||
def _match_grams(query: Iterable[str], test: Iterable[str]) -> bool:
|
|
||||||
''' Check if grams from test fit query. '''
|
|
||||||
for gram in test:
|
|
||||||
if not gram in query:
|
|
||||||
if not gram in WordTag.PARTS_OF_SPEECH:
|
|
||||||
return False
|
|
||||||
for pos in WordTag.PARTS_OF_SPEECH:
|
|
||||||
if pos in query:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def _search_form(query: Iterable[str], data: Iterable[TermForm]) -> Optional[str]:
|
|
||||||
for form in data:
|
|
||||||
if _match_grams(query, form['grams']):
|
|
||||||
return form['text']
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
class Entity:
|
|
||||||
''' Represents text entity. '''
|
|
||||||
def __init__(self, alias: str, nominal: str, manual_forms: Optional[Iterable[TermForm]]=None):
|
|
||||||
if manual_forms is None:
|
|
||||||
self.manual = []
|
|
||||||
else:
|
|
||||||
self.manual = list(manual_forms)
|
|
||||||
self.alias = alias
|
|
||||||
self._nominal = nominal
|
|
||||||
self._cached: list[TermForm] = []
|
|
||||||
|
|
||||||
def get_nominal(self) -> str:
|
|
||||||
''' Getter for _nominal. '''
|
|
||||||
return self._nominal
|
|
||||||
|
|
||||||
def set_nominal(self, new_text: str):
|
|
||||||
''' Setter for _nominal.
|
|
||||||
Note: clears manual and cached forms. '''
|
|
||||||
if self._nominal == new_text:
|
|
||||||
return
|
|
||||||
self._nominal = new_text
|
|
||||||
self.manual = []
|
|
||||||
self._cached = []
|
|
||||||
|
|
||||||
def get_form(self, grams: Iterable[str]) -> str:
|
|
||||||
''' Get specific term form. '''
|
|
||||||
if all(False for _ in grams):
|
|
||||||
return self._nominal
|
|
||||||
text = _search_form(grams, self.manual)
|
|
||||||
if text is not None:
|
|
||||||
return text
|
|
||||||
text = _search_form(grams, self._cached)
|
|
||||||
if text is not None:
|
|
||||||
return text
|
|
||||||
|
|
||||||
model = parser.parse(self._nominal)
|
|
||||||
if model is None:
|
|
||||||
text = self._nominal
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
text = model.inflect(grams)
|
|
||||||
except ValueError as error:
|
|
||||||
text = f'!{error}!'.replace('Unknown grammeme', 'Неизвестная граммема')
|
|
||||||
self._cached.append({'text': text, 'grams': grams})
|
|
||||||
return text
|
|
||||||
|
|
||||||
|
|
||||||
# Represents term context for resolving entity references.
|
|
||||||
TermContext = dict[str, Entity]
|
|
|
@ -1,60 +0,0 @@
|
||||||
''' Text reference API. '''
|
|
||||||
from enum import Enum, unique
|
|
||||||
from typing import Optional, Union
|
|
||||||
|
|
||||||
|
|
||||||
@unique
|
|
||||||
class ReferenceType(Enum):
|
|
||||||
''' Text reference types. '''
|
|
||||||
entity = 'entity'
|
|
||||||
syntactic = 'syntax'
|
|
||||||
|
|
||||||
|
|
||||||
class EntityReference:
|
|
||||||
''' Reference to entity. '''
|
|
||||||
|
|
||||||
def __init__(self, identifier: str, form: str):
|
|
||||||
self.entity = identifier
|
|
||||||
self.form = form
|
|
||||||
|
|
||||||
def get_type(self) -> ReferenceType:
|
|
||||||
return ReferenceType.entity
|
|
||||||
|
|
||||||
def to_text(self) -> str:
|
|
||||||
return f'@{{{self.entity}|{self.form}}}'
|
|
||||||
|
|
||||||
|
|
||||||
class SyntacticReference:
|
|
||||||
''' Reference to syntactic dependency on EntityReference. '''
|
|
||||||
|
|
||||||
def __init__(self, referral_offset: int, text: str):
|
|
||||||
self.nominal = text
|
|
||||||
self.offset = referral_offset
|
|
||||||
|
|
||||||
def get_type(self) -> ReferenceType:
|
|
||||||
return ReferenceType.syntactic
|
|
||||||
|
|
||||||
def to_text(self) -> str:
|
|
||||||
return f'@{{{self.offset}|{self.nominal}}}'
|
|
||||||
|
|
||||||
|
|
||||||
Reference = Union[EntityReference, SyntacticReference]
|
|
||||||
|
|
||||||
|
|
||||||
def parse_reference(text: str) -> Optional[Reference]:
|
|
||||||
if len(text) < 4 or text[-1] != '}' or text[0:2] != '@{':
|
|
||||||
return None
|
|
||||||
blocks: list[str] = [block.strip() for block in text[2:-1].split('|')]
|
|
||||||
if len(blocks) != 2 or blocks[0] == '' or blocks[0][0] in '0':
|
|
||||||
return None
|
|
||||||
if blocks[0][0] in '-123456789':
|
|
||||||
if blocks[1] == '':
|
|
||||||
return None
|
|
||||||
try:
|
|
||||||
offset = int(blocks[0])
|
|
||||||
return SyntacticReference(offset, blocks[1])
|
|
||||||
except ValueError:
|
|
||||||
return None
|
|
||||||
else:
|
|
||||||
form = blocks[1].replace(' ', '')
|
|
||||||
return EntityReference(blocks[0], form)
|
|
|
@ -1,140 +0,0 @@
|
||||||
''' Reference resolution API. '''
|
|
||||||
import re
|
|
||||||
from typing import cast, Optional
|
|
||||||
from dataclasses import dataclass
|
|
||||||
|
|
||||||
from .rumodel import split_grams
|
|
||||||
|
|
||||||
from .conceptapi import inflect_dependant
|
|
||||||
from .context import TermContext
|
|
||||||
from .reference import EntityReference, SyntacticReference, parse_reference, Reference
|
|
||||||
|
|
||||||
|
|
||||||
_REF_ENTITY_PATTERN = re.compile(r'@{([^0-9\-][^\}\|\{]*?)\|([^\}\|\{]*?)}')
|
|
||||||
|
|
||||||
|
|
||||||
def extract_entities(text: str) -> list[str]:
|
|
||||||
''' Extract list of entities that are referenced. '''
|
|
||||||
result: list[str] = []
|
|
||||||
for segment in re.finditer(_REF_ENTITY_PATTERN, text):
|
|
||||||
entity = segment.group(1)
|
|
||||||
if entity not in result:
|
|
||||||
result.append(entity)
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def resolve_entity(ref: EntityReference, context: TermContext) -> str:
|
|
||||||
''' Resolve entity reference. '''
|
|
||||||
alias = ref.entity
|
|
||||||
if alias not in context:
|
|
||||||
return f'!Неизвестная сущность: {alias}!'
|
|
||||||
grams = split_grams(ref.form)
|
|
||||||
resolved = context[alias].get_form(grams)
|
|
||||||
if resolved == '':
|
|
||||||
return f'!Отсутствует термин: {alias}!'
|
|
||||||
else:
|
|
||||||
return resolved
|
|
||||||
|
|
||||||
|
|
||||||
def resolve_syntactic(ref: SyntacticReference, index: int, references: list['ResolvedReference']) -> str:
|
|
||||||
''' Resolve syntactic reference. '''
|
|
||||||
offset = ref.offset
|
|
||||||
master: Optional['ResolvedReference'] = None
|
|
||||||
if offset > 0:
|
|
||||||
index += 1
|
|
||||||
while index < len(references):
|
|
||||||
if isinstance(references[index].ref, EntityReference):
|
|
||||||
if offset == 1:
|
|
||||||
master = references[index]
|
|
||||||
else:
|
|
||||||
offset -= 1
|
|
||||||
index += 1
|
|
||||||
else:
|
|
||||||
index -= 1
|
|
||||||
while index >= 0:
|
|
||||||
if isinstance(references[index].ref, EntityReference):
|
|
||||||
if offset == -1:
|
|
||||||
master = references[index]
|
|
||||||
else:
|
|
||||||
offset += 1
|
|
||||||
index -= 1
|
|
||||||
if master is None:
|
|
||||||
return f'!Некорректное смещение: {ref.offset}!'
|
|
||||||
return inflect_dependant(ref.nominal, master.resolved)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Position:
|
|
||||||
''' 0-indexed contiguous segment position in text. '''
|
|
||||||
start: int = 0
|
|
||||||
finish: int = 0
|
|
||||||
|
|
||||||
def __hash__(self) -> int:
|
|
||||||
return hash((self.start, self.finish))
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class ResolvedReference:
|
|
||||||
''' Resolved reference data '''
|
|
||||||
ref: Reference
|
|
||||||
resolved: str = ''
|
|
||||||
pos_input: Position = Position()
|
|
||||||
pos_output: Position = Position()
|
|
||||||
|
|
||||||
def __hash__(self) -> int:
|
|
||||||
return hash((self.resolved, self.pos_input, self.pos_output, self.ref.to_text()))
|
|
||||||
|
|
||||||
|
|
||||||
class Resolver:
|
|
||||||
''' Text reference resolver '''
|
|
||||||
REFERENCE_PATTERN = re.compile(r'@{[^\}\{]*?}')
|
|
||||||
|
|
||||||
def __init__(self, context: TermContext):
|
|
||||||
self.context = context
|
|
||||||
self.refs = cast(list[ResolvedReference], [])
|
|
||||||
self.input = ''
|
|
||||||
self.output = ''
|
|
||||||
|
|
||||||
def resolve(self, text: str) -> str:
|
|
||||||
''' Resolve references in input text.
|
|
||||||
Note: data on references positions is accessed through class attributes '''
|
|
||||||
self._reset(text)
|
|
||||||
self._parse_refs()
|
|
||||||
if len(self.refs) == 0:
|
|
||||||
self.output = self.input
|
|
||||||
return self.output
|
|
||||||
else:
|
|
||||||
self._resolve_refs()
|
|
||||||
self._combine_output()
|
|
||||||
return self.output
|
|
||||||
|
|
||||||
def _reset(self, input_text: str):
|
|
||||||
self.refs = cast(list[ResolvedReference], [])
|
|
||||||
self.input = input_text
|
|
||||||
self.output = ''
|
|
||||||
|
|
||||||
def _parse_refs(self):
|
|
||||||
for segment in re.finditer(Resolver.REFERENCE_PATTERN, self.input):
|
|
||||||
parse = parse_reference(segment[0])
|
|
||||||
if parse is not None:
|
|
||||||
ref_info = ResolvedReference(ref=parse,
|
|
||||||
resolved='',
|
|
||||||
pos_input=Position(segment.start(0), segment.end(0)))
|
|
||||||
self.refs.append(ref_info)
|
|
||||||
|
|
||||||
def _resolve_refs(self):
|
|
||||||
for ref in self.refs:
|
|
||||||
if isinstance(ref.ref, EntityReference):
|
|
||||||
ref.resolved = resolve_entity(ref.ref, self.context)
|
|
||||||
for (index, ref) in enumerate(self.refs):
|
|
||||||
if isinstance(ref.ref, SyntacticReference):
|
|
||||||
ref.resolved = resolve_syntactic(ref.ref, index, self.refs)
|
|
||||||
|
|
||||||
def _combine_output(self):
|
|
||||||
pos_in = 0
|
|
||||||
for ref in self.refs:
|
|
||||||
self.output += self.input[pos_in : ref.pos_input.start]
|
|
||||||
self.output += ref.resolved
|
|
||||||
ref.pos_output = Position(len(self.output) - len(ref.resolved), len(self.output))
|
|
||||||
pos_in = ref.pos_input.finish
|
|
||||||
self.output += self.input[pos_in : len(self.input)]
|
|
|
@ -1,118 +0,0 @@
|
||||||
''' Russian language models. '''
|
|
||||||
from __future__ import annotations
|
|
||||||
from enum import Enum, unique
|
|
||||||
from typing import Iterable, Optional
|
|
||||||
|
|
||||||
from pymorphy3 import MorphAnalyzer
|
|
||||||
from pymorphy3.tagset import OpencorporaTag as WordTag
|
|
||||||
|
|
||||||
# ''' Morphology parser. '''
|
|
||||||
morpho = MorphAnalyzer()
|
|
||||||
Grammemes = Iterable[str]
|
|
||||||
|
|
||||||
|
|
||||||
def split_grams(text: str) -> list[str]:
|
|
||||||
''' Split grammemes string into set of items. '''
|
|
||||||
return [tag.strip() for tag in filter(None, text.split(','))]
|
|
||||||
|
|
||||||
|
|
||||||
def combine_grams(tags: Iterable[str]) -> str:
|
|
||||||
''' Combine grammemes into string. '''
|
|
||||||
return ','.join(tags)
|
|
||||||
|
|
||||||
|
|
||||||
@unique
|
|
||||||
class SemanticRole(Enum):
|
|
||||||
''' Enumerating semantic types for different parse patterns. '''
|
|
||||||
unknwn = 0
|
|
||||||
term = 1
|
|
||||||
action = 2
|
|
||||||
definition = 3
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def from_POS(pos: Optional[str]) -> SemanticRole:
|
|
||||||
''' Production method: types from part of speech. '''
|
|
||||||
if pos in ['NOUN', 'NPRO']:
|
|
||||||
return SemanticRole.term
|
|
||||||
elif pos in ['VERB', 'INFN', 'PRTF', 'PRTS']:
|
|
||||||
return SemanticRole.action
|
|
||||||
elif pos in ['ADJF', 'ADJS']:
|
|
||||||
return SemanticRole.definition
|
|
||||||
return SemanticRole.unknwn
|
|
||||||
|
|
||||||
|
|
||||||
class Morphology:
|
|
||||||
''' Wrapper for OpencorporaTag expanding functionality for multiword.
|
|
||||||
Full morphology tags see http://opencorpora.org/dict.php?act=gram
|
|
||||||
'''
|
|
||||||
def __init__(self, tag: WordTag, semantic=SemanticRole.unknwn):
|
|
||||||
self.tag = tag
|
|
||||||
self.semantic = semantic if semantic != SemanticRole.unknwn else SemanticRole.from_POS(tag.POS)
|
|
||||||
|
|
||||||
_TAGS_IMMUTABLE = frozenset(['INFN', 'ADVB', 'COMP', 'PNCT', 'PREP', 'CONJ', 'PRCL', 'INTJ'])
|
|
||||||
|
|
||||||
_TAGS_NO_TENSE = frozenset(['NOUN', 'NPRO', 'ADJF', 'ADJS'])
|
|
||||||
_TAGS_NO_CASE = frozenset(['GRND', 'VERB', 'ADJS', 'PRTS'])
|
|
||||||
_TAGS_NO_NUMBER = frozenset(['GRND'])
|
|
||||||
_TAGS_NO_GENDER = frozenset(['GRND', 'NOUN', 'NPRO', 'plur'])
|
|
||||||
_TAGS_NO_PERSON = frozenset(['GRND', 'NOUN', 'ADJF', 'ADJS', 'PRTF', 'PRTS', 'past'])
|
|
||||||
|
|
||||||
@property
|
|
||||||
def can_coordinate(self) -> bool:
|
|
||||||
''' Check if coordination can change text. '''
|
|
||||||
return self.tag.POS in ['NOUN', 'NPRO', 'NUMR', 'ADJF', 'ADJS', 'PRTF', 'PRTS']
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def is_dependable(pos: str):
|
|
||||||
''' Check if this morphology can be dependant. '''
|
|
||||||
return pos in ['ADJF', 'ADJS', 'PRTF', 'PRTS']
|
|
||||||
|
|
||||||
@property
|
|
||||||
def effective_POS(self) -> Optional[str]:
|
|
||||||
''' Access part of speech. Pronouns are considered as nouns '''
|
|
||||||
pos: Optional[str] = self.tag.POS
|
|
||||||
if pos and self.tag.POS == 'NPRO':
|
|
||||||
return 'NOUN'
|
|
||||||
return pos
|
|
||||||
|
|
||||||
def complete_grams(self, grams: Iterable[str]) -> set[str]:
|
|
||||||
''' Add missing tags before inflection. '''
|
|
||||||
result = set(grams)
|
|
||||||
pos = self.tag.POS
|
|
||||||
if pos and result.isdisjoint(WordTag.PARTS_OF_SPEECH):
|
|
||||||
result.add(pos if pos != 'INFN' or len(result) == 0 else 'VERB')
|
|
||||||
if not result.isdisjoint(self._TAGS_IMMUTABLE):
|
|
||||||
return result
|
|
||||||
if self.tag.case and result.isdisjoint(WordTag.CASES) and result.isdisjoint(self._TAGS_NO_CASE):
|
|
||||||
result.add(self.tag.case)
|
|
||||||
if self.tag.tense and result.isdisjoint(WordTag.TENSES) and result.isdisjoint(self._TAGS_NO_TENSE):
|
|
||||||
if (self.tag.tense != 'past' or result.isdisjoint(WordTag.PERSONS)) \
|
|
||||||
and (self.tag.tense != 'pres' or result.isdisjoint(WordTag.GENDERS)):
|
|
||||||
result.add(self.tag.tense)
|
|
||||||
if self.tag.number and result.isdisjoint(WordTag.NUMBERS) and result.isdisjoint(self._TAGS_NO_NUMBER):
|
|
||||||
if self.tag.number != 'plur' or result.isdisjoint(WordTag.GENDERS):
|
|
||||||
result.add(self.tag.number)
|
|
||||||
if self.tag.gender and result.isdisjoint(WordTag.GENDERS) and result.isdisjoint(self._TAGS_NO_GENDER):
|
|
||||||
if 'PRTF' in result or 'pres' not in result:
|
|
||||||
result.add(self.tag.gender)
|
|
||||||
if self.tag.person and result.isdisjoint(WordTag.PERSONS) and result.isdisjoint(self._TAGS_NO_PERSON):
|
|
||||||
result.add(self.tag.person)
|
|
||||||
if 'plur' in result and not result.isdisjoint(WordTag.GENDERS):
|
|
||||||
result = result.difference(WordTag.GENDERS)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def coordination_grams(self) -> set[str]:
|
|
||||||
''' Return set of grammemes for inflection to keep coordination . '''
|
|
||||||
result = set()
|
|
||||||
if self.tag.case:
|
|
||||||
result.add(self.tag.case)
|
|
||||||
if self.tag:
|
|
||||||
number = self.tag.number
|
|
||||||
result.add(number)
|
|
||||||
if self.tag.gender and 'plur' not in result:
|
|
||||||
result.add(self.tag.gender)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def to_text(self) -> str:
|
|
||||||
''' Produce string of all grammemes. '''
|
|
||||||
return combine_grams(self.tag.grammemes)
|
|
|
@ -1,486 +0,0 @@
|
||||||
''' Parsing russian language using pymorphy3 library. '''
|
|
||||||
from __future__ import annotations
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
from razdel.substring import Substring as Segment
|
|
||||||
from pymorphy3.analyzer import Parse as WordParse
|
|
||||||
|
|
||||||
from .syntax import RuSyntax, Capitalization
|
|
||||||
from .rumodel import SemanticRole, Morphology, WordTag, morpho, Grammemes
|
|
||||||
|
|
||||||
INDEX_NONE = -1
|
|
||||||
NO_COORDINATION = -1
|
|
||||||
WORD_NONE = -1
|
|
||||||
|
|
||||||
|
|
||||||
class WordToken:
|
|
||||||
''' Atomic text token. '''
|
|
||||||
def __init__(self, segment: Segment, parse: list[WordParse], main_parse: int = 0):
|
|
||||||
self.segment: Segment = segment
|
|
||||||
self.forms: list[WordParse] = parse
|
|
||||||
self.main: int = main_parse
|
|
||||||
|
|
||||||
def get_morpho(self) -> Morphology:
|
|
||||||
''' Return morphology for current token. '''
|
|
||||||
return Morphology(self.get_parse().tag)
|
|
||||||
|
|
||||||
def get_parse(self) -> WordParse:
|
|
||||||
''' Access main form. '''
|
|
||||||
return self.forms[self.main]
|
|
||||||
|
|
||||||
def inflect(self, inflection_grams: set[str]) -> Optional[WordParse]:
|
|
||||||
''' Apply inflection to segment text. Does not modify forms '''
|
|
||||||
inflected = self.get_parse().inflect(inflection_grams)
|
|
||||||
if not inflected:
|
|
||||||
return None
|
|
||||||
self.segment.text = Capitalization.from_text(self.segment.text).apply_to(inflected.word)
|
|
||||||
return inflected
|
|
||||||
|
|
||||||
|
|
||||||
class Collation:
|
|
||||||
''' Parsed data for input coordinated text. '''
|
|
||||||
def __init__(self, text: str):
|
|
||||||
self.text = text
|
|
||||||
self.words: list[WordToken] = []
|
|
||||||
self.coordination: list[int] = []
|
|
||||||
self.main_word: int = WORD_NONE
|
|
||||||
|
|
||||||
def is_valid(self) -> bool:
|
|
||||||
''' Check if data is parsed correctly '''
|
|
||||||
return self.main_word != WORD_NONE
|
|
||||||
|
|
||||||
def get_form(self) -> WordParse:
|
|
||||||
''' Access WordParse. '''
|
|
||||||
return self.words[self.main_word].get_parse()
|
|
||||||
|
|
||||||
def get_morpho(self) -> Morphology:
|
|
||||||
''' Access parsed main morphology. '''
|
|
||||||
return self.words[self.main_word].get_morpho()
|
|
||||||
|
|
||||||
def add_word(self, segment, forms: list, main_form: int, need_coordination: bool = True):
|
|
||||||
''' Add word information. '''
|
|
||||||
self.words.append(WordToken(segment, forms, main_form))
|
|
||||||
self.coordination.append(NO_COORDINATION if not need_coordination else 0)
|
|
||||||
|
|
||||||
def inflect(self, target_grams: Grammemes) -> str:
|
|
||||||
''' Inflect text to match required tags. '''
|
|
||||||
if self.is_valid():
|
|
||||||
origin = self.get_morpho()
|
|
||||||
if not origin.tag.grammemes.issuperset(target_grams):
|
|
||||||
if self._apply_inflection(origin, target_grams):
|
|
||||||
return self._generate_text()
|
|
||||||
return self.text
|
|
||||||
|
|
||||||
def inflect_like(self, base_model: Collation) -> str:
|
|
||||||
''' Create inflection to substitute base_model form. '''
|
|
||||||
if self.is_valid():
|
|
||||||
morph = base_model.get_morpho()
|
|
||||||
if morph.effective_POS:
|
|
||||||
tags = set()
|
|
||||||
tags.add(morph.effective_POS)
|
|
||||||
tags = morph.complete_grams(tags)
|
|
||||||
return self.inflect(tags)
|
|
||||||
return self.text
|
|
||||||
|
|
||||||
def inflect_dependant(self, master_model: Collation) -> str:
|
|
||||||
''' Create inflection to coordinate with master_model form. '''
|
|
||||||
assert self.is_valid()
|
|
||||||
morph = master_model.get_morpho()
|
|
||||||
tags = morph.coordination_grams()
|
|
||||||
tags = self.get_morpho().complete_grams(tags)
|
|
||||||
return self.inflect(tags)
|
|
||||||
|
|
||||||
def normal_form(self) -> str:
|
|
||||||
''' Generate normal form. '''
|
|
||||||
if self.is_valid():
|
|
||||||
main_form = self.get_form()
|
|
||||||
new_morpho = Morphology(main_form.normalized.tag)
|
|
||||||
new_grams = new_morpho.complete_grams(frozenset())
|
|
||||||
return self.inflect(new_grams)
|
|
||||||
return self.text
|
|
||||||
|
|
||||||
def _iterate_coordinated(self):
|
|
||||||
words_count = len(self.words)
|
|
||||||
current_word = self.coordination[words_count]
|
|
||||||
while current_word != words_count:
|
|
||||||
yield self.words[current_word]
|
|
||||||
current_word += self.coordination[current_word]
|
|
||||||
|
|
||||||
def _inflect_main_word(self, origin: Morphology, target_grams: Grammemes) -> Optional[Morphology]:
|
|
||||||
full_grams = origin.complete_grams(target_grams)
|
|
||||||
inflected = self.words[self.main_word].inflect(full_grams)
|
|
||||||
if not inflected:
|
|
||||||
return None
|
|
||||||
return Morphology(inflected.tag)
|
|
||||||
|
|
||||||
def _apply_inflection(self, origin: Morphology, target_grams: Grammemes) -> bool:
|
|
||||||
new_moprho = self._inflect_main_word(origin, target_grams)
|
|
||||||
if not new_moprho:
|
|
||||||
return False
|
|
||||||
inflection_grams = new_moprho.coordination_grams()
|
|
||||||
if len(inflection_grams) == 0:
|
|
||||||
return True
|
|
||||||
for word in self._iterate_coordinated():
|
|
||||||
word.inflect(inflection_grams)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def _generate_text(self) -> str:
|
|
||||||
current_pos = 0
|
|
||||||
result = ''
|
|
||||||
for token in self.words:
|
|
||||||
if token.segment.start > current_pos:
|
|
||||||
result += self.text[current_pos: token.segment.start]
|
|
||||||
result += token.segment.text
|
|
||||||
current_pos = token.segment.stop
|
|
||||||
if current_pos + 1 < len(self.text):
|
|
||||||
result += self.text[current_pos:]
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
class PhraseParser:
|
|
||||||
''' Russian grammar parser. '''
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
_FILTER_SCORE = 0.005
|
|
||||||
_SINGLE_SCORE_SEARCH = 0.2
|
|
||||||
_PRIORITY_NONE = NO_COORDINATION
|
|
||||||
|
|
||||||
_MAIN_WAIT_LIMIT = 10 # count words until fixing main
|
|
||||||
_MAIN_MAX_FOLLOWERS = 3 # count words after main as coordination candidates
|
|
||||||
|
|
||||||
def parse(self, text: str,
|
|
||||||
require_index: int = INDEX_NONE,
|
|
||||||
require_grams: Optional[Grammemes] = None) -> Optional[Collation]:
|
|
||||||
'''
|
|
||||||
Determine morpho tags for input text.
|
|
||||||
::returns:: Morphology of a text or None if no suitable form is available
|
|
||||||
'''
|
|
||||||
segments = list(RuSyntax.tokenize(text))
|
|
||||||
if len(segments) == 0:
|
|
||||||
return None
|
|
||||||
elif len(segments) == 1:
|
|
||||||
return self._parse_single(segments[0], require_index, require_grams)
|
|
||||||
else:
|
|
||||||
return self._parse_multiword(text, segments, require_index, require_grams)
|
|
||||||
|
|
||||||
def normalize(self, text: str):
|
|
||||||
''' Get normal form for target text. '''
|
|
||||||
processed = self.parse(text)
|
|
||||||
if processed:
|
|
||||||
return processed.normal_form()
|
|
||||||
return text
|
|
||||||
|
|
||||||
def find_substr(self, text: str, sub: str) -> tuple[int, int]:
|
|
||||||
''' Search for substring position in text regardless of morphology. '''
|
|
||||||
if not text or not sub:
|
|
||||||
return (0, 0)
|
|
||||||
query = [self.normalize(elem.text) for elem in RuSyntax.tokenize(sub)]
|
|
||||||
query_len = len(query)
|
|
||||||
start = 0
|
|
||||||
current_index = 0
|
|
||||||
for token in RuSyntax.tokenize(text):
|
|
||||||
text_word = self.normalize(token.text)
|
|
||||||
if text_word != query[current_index]:
|
|
||||||
current_index = 0
|
|
||||||
else:
|
|
||||||
if current_index == 0:
|
|
||||||
start = token.start
|
|
||||||
current_index += 1
|
|
||||||
if current_index == query_len:
|
|
||||||
return (start, token.stop)
|
|
||||||
return (0, 0)
|
|
||||||
|
|
||||||
def inflect_context(self, text: str, before: str = '', after: str = '') -> str:
|
|
||||||
''' Inflect text in accordance to context before and after. '''
|
|
||||||
target = self.parse(text)
|
|
||||||
if not target:
|
|
||||||
return text
|
|
||||||
target_morpho = target.get_morpho()
|
|
||||||
if not target_morpho or not target_morpho.can_coordinate:
|
|
||||||
return text
|
|
||||||
|
|
||||||
model_after = self.parse(after)
|
|
||||||
model_before = self.parse(before)
|
|
||||||
etalon = PhraseParser._choose_context_etalon(target_morpho, model_before, model_after)
|
|
||||||
if not etalon:
|
|
||||||
return text
|
|
||||||
etalon_moprho = etalon.get_morpho()
|
|
||||||
if not etalon_moprho.can_coordinate:
|
|
||||||
return text
|
|
||||||
|
|
||||||
new_form = PhraseParser._combine_morpho(target_morpho, etalon_moprho.tag)
|
|
||||||
return target.inflect(new_form)
|
|
||||||
|
|
||||||
def inflect_substitute(self, substitute_normal: str, original: str) -> str:
|
|
||||||
''' Inflect substitute to match original form. '''
|
|
||||||
original_model = self.parse(original)
|
|
||||||
if not original_model:
|
|
||||||
return substitute_normal
|
|
||||||
substitute_model = self.parse(substitute_normal)
|
|
||||||
if not substitute_model:
|
|
||||||
return substitute_normal
|
|
||||||
return substitute_model.inflect_like(original_model)
|
|
||||||
|
|
||||||
def inflect_dependant(self, dependant_normal: str, master: str) -> str:
|
|
||||||
''' Inflect dependant to coordinate with master text. '''
|
|
||||||
master_model = self.parse(master)
|
|
||||||
if not master_model:
|
|
||||||
return dependant_normal
|
|
||||||
dependant_model = self.parse(dependant_normal)
|
|
||||||
if not dependant_model:
|
|
||||||
return dependant_normal
|
|
||||||
return dependant_model.inflect_dependant(master_model)
|
|
||||||
|
|
||||||
def _parse_single(self, segment, require_index: int, require_grams: Optional[Grammemes]) -> Optional[Collation]:
|
|
||||||
forms = list(self._filtered_parse(segment.text))
|
|
||||||
parse_index = INDEX_NONE
|
|
||||||
if len(forms) == 0 or require_index >= len(forms):
|
|
||||||
return None
|
|
||||||
|
|
||||||
if require_index != INDEX_NONE:
|
|
||||||
tags = forms[require_index].tag
|
|
||||||
if require_grams and not tags.grammemes.issuperset(require_grams):
|
|
||||||
return None
|
|
||||||
parse_index = require_index
|
|
||||||
else:
|
|
||||||
current_score = 0
|
|
||||||
for (index, form) in enumerate(forms):
|
|
||||||
if not require_grams or form.tag.grammemes.issuperset(require_grams):
|
|
||||||
if form.tag.case == 'nomn':
|
|
||||||
parse_index = index
|
|
||||||
break
|
|
||||||
elif parse_index == INDEX_NONE:
|
|
||||||
current_score = form.score
|
|
||||||
parse_index = index
|
|
||||||
elif form.score / current_score < self._SINGLE_SCORE_SEARCH:
|
|
||||||
break
|
|
||||||
|
|
||||||
if parse_index == INDEX_NONE:
|
|
||||||
return None
|
|
||||||
result = Collation(segment.text)
|
|
||||||
result.add_word(segment, [forms[parse_index]], main_form=0, need_coordination=False)
|
|
||||||
result.coordination.append(len(result.words))
|
|
||||||
result.main_word = 0
|
|
||||||
return result
|
|
||||||
|
|
||||||
def _parse_multiword(self, text: str, segments: list, require_index: int,
|
|
||||||
require_grams: Optional[Grammemes]) -> Optional[Collation]:
|
|
||||||
result = Collation(text)
|
|
||||||
priority_main: float = self._PRIORITY_NONE
|
|
||||||
segment_index = 0
|
|
||||||
main_wait = 0
|
|
||||||
word_index = 0
|
|
||||||
for segment in segments:
|
|
||||||
if main_wait > PhraseParser._MAIN_WAIT_LIMIT:
|
|
||||||
break
|
|
||||||
segment_index += 1
|
|
||||||
priority = self._parse_segment(result, segment, require_index, require_grams)
|
|
||||||
if priority is None:
|
|
||||||
continue # skip non-parsable entities
|
|
||||||
main_wait += 1
|
|
||||||
if priority > priority_main:
|
|
||||||
result.main_word = word_index
|
|
||||||
priority_main = priority
|
|
||||||
word_index += 1
|
|
||||||
if result.main_word == INDEX_NONE:
|
|
||||||
return None
|
|
||||||
self._finalize_coordination(result)
|
|
||||||
if segment_index < len(segments):
|
|
||||||
pass # finish to parse segments after main if needed
|
|
||||||
return result
|
|
||||||
|
|
||||||
def _parse_segment(self,
|
|
||||||
output: Collation,
|
|
||||||
segment: Segment,
|
|
||||||
require_index: int,
|
|
||||||
require_grams: Optional[Grammemes]) -> Optional[float]:
|
|
||||||
''' Return priority for this can be a new main word '''
|
|
||||||
forms = list(self._filtered_parse(segment.text))
|
|
||||||
if len(forms) == 0:
|
|
||||||
return None
|
|
||||||
main_index: int = INDEX_NONE
|
|
||||||
segment_score: float = self._PRIORITY_NONE
|
|
||||||
needs_coordination = False
|
|
||||||
local_sum: float = 0
|
|
||||||
score_sum: float = 0
|
|
||||||
if require_index != INDEX_NONE:
|
|
||||||
form = forms[require_index]
|
|
||||||
if not require_grams or form.tag.grammemes.issuperset(require_grams):
|
|
||||||
(local_max, segment_score) = PhraseParser._get_priorities_for(form.tag)
|
|
||||||
main_index = require_index
|
|
||||||
needs_coordination = Morphology.is_dependable(form.tag.POS)
|
|
||||||
else:
|
|
||||||
local_max = self._PRIORITY_NONE
|
|
||||||
for (index, form) in enumerate(forms):
|
|
||||||
if require_grams and not form.tag.grammemes.issuperset(require_grams):
|
|
||||||
continue
|
|
||||||
(local_priority, global_priority) = PhraseParser._get_priorities_for(form.tag)
|
|
||||||
needs_coordination = needs_coordination or Morphology.is_dependable(form.tag.POS)
|
|
||||||
local_sum += global_priority * form.score
|
|
||||||
score_sum += form.score
|
|
||||||
if local_priority > local_max:
|
|
||||||
local_max = local_priority
|
|
||||||
# segment_score = global_priority
|
|
||||||
main_index = index
|
|
||||||
if score_sum == 0:
|
|
||||||
return None
|
|
||||||
segment_score = local_sum / score_sum
|
|
||||||
output.add_word(segment, forms, main_index, needs_coordination)
|
|
||||||
return segment_score
|
|
||||||
# Alternative: return segment_score
|
|
||||||
# penalty_suspicious = 0 if local_max == 0 else (1 - local_sum / local_max) * self._PRIORITY_PENALTY
|
|
||||||
# return segment_score - penalty_suspicious
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _finalize_coordination(cls, target: Collation):
|
|
||||||
main_morpho: Morphology = target.get_morpho()
|
|
||||||
main_coordinate = main_morpho.can_coordinate
|
|
||||||
target.coordination[target.main_word] = NO_COORDINATION
|
|
||||||
first_change = INDEX_NONE
|
|
||||||
current_len = 0
|
|
||||||
for (index, word) in enumerate(target.words):
|
|
||||||
if target.coordination[index] == NO_COORDINATION or index - target.main_word > cls._MAIN_MAX_FOLLOWERS:
|
|
||||||
needs_change = False
|
|
||||||
if index != target.main_word:
|
|
||||||
word.main = INDEX_NONE
|
|
||||||
else:
|
|
||||||
word.main = PhraseParser._find_coordination(word.forms, main_morpho.tag, index < target.main_word)
|
|
||||||
needs_change = word.main != INDEX_NONE
|
|
||||||
if not needs_change or not main_coordinate:
|
|
||||||
target.coordination[index] = NO_COORDINATION
|
|
||||||
current_len += 1
|
|
||||||
if needs_change and main_coordinate:
|
|
||||||
target.coordination[index] = current_len
|
|
||||||
current_len = 0
|
|
||||||
if first_change == INDEX_NONE:
|
|
||||||
first_change = index
|
|
||||||
if first_change == INDEX_NONE:
|
|
||||||
target.coordination.append(len(target.words))
|
|
||||||
return
|
|
||||||
previous_reference = first_change
|
|
||||||
current_word = len(target.words)
|
|
||||||
target.coordination.append(current_len + 1)
|
|
||||||
while target.coordination[current_word] != INDEX_NONE:
|
|
||||||
previous_word = current_word - target.coordination[current_word]
|
|
||||||
target.coordination[current_word] = previous_reference
|
|
||||||
previous_reference = current_word - previous_word
|
|
||||||
current_word = previous_word
|
|
||||||
if previous_reference == 0 or current_word < 0:
|
|
||||||
break
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _find_coordination(forms: list, main_tag: WordTag, before_main: bool) -> int:
|
|
||||||
for (index, form) in enumerate(forms):
|
|
||||||
pos = form.tag.POS
|
|
||||||
case = form.tag.case
|
|
||||||
if pos not in ['ADJF', 'ADJS', 'PRTF', 'PRTS']:
|
|
||||||
continue
|
|
||||||
if SemanticRole.from_POS(pos) == SemanticRole.term and case == 'gent':
|
|
||||||
if before_main:
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
return INDEX_NONE
|
|
||||||
if case == main_tag.case:
|
|
||||||
return index
|
|
||||||
elif main_tag.case in ['accs', 'gent'] and case in ['accs', 'gent']:
|
|
||||||
return index
|
|
||||||
return INDEX_NONE
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _filtered_parse(text: str):
|
|
||||||
capital = Capitalization.from_text(text)
|
|
||||||
score_filter = PhraseParser._filter_score(morpho.parse(text))
|
|
||||||
yield from PhraseParser._filter_capital(score_filter, capital)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _filter_score(generator):
|
|
||||||
for form in generator:
|
|
||||||
if form.score < PhraseParser._FILTER_SCORE:
|
|
||||||
break
|
|
||||||
yield form
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _filter_capital(generator, capital: Capitalization):
|
|
||||||
if capital in [Capitalization.upper_case, Capitalization.mixed]:
|
|
||||||
for form in generator:
|
|
||||||
if 'Abbr' not in form.tag.grammemes:
|
|
||||||
continue
|
|
||||||
yield form
|
|
||||||
else:
|
|
||||||
yield from generator
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _parse_word(text: str, require_index: int = INDEX_NONE,
|
|
||||||
require_grams: Optional[Grammemes] = None) -> Optional[Morphology]:
|
|
||||||
parsed_variants = morpho.parse(text)
|
|
||||||
if not parsed_variants or require_index >= len(parsed_variants):
|
|
||||||
return None
|
|
||||||
if require_index != INDEX_NONE:
|
|
||||||
tags = parsed_variants[require_index].tag
|
|
||||||
if not require_grams or tags.grammemes.issuperset(require_grams):
|
|
||||||
return Morphology(tags)
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
else:
|
|
||||||
for variant in parsed_variants:
|
|
||||||
tags = variant.tag
|
|
||||||
if not require_grams or tags.grammemes.issuperset(require_grams):
|
|
||||||
return Morphology(tags)
|
|
||||||
return None
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _get_priorities_for(tag: WordTag) -> tuple[float, float]:
|
|
||||||
''' Return pair of local and global priorities. '''
|
|
||||||
if tag.POS in ['VERB', 'INFN']:
|
|
||||||
return (9, 10)
|
|
||||||
if tag.POS in ['NOUN', 'NPRO']:
|
|
||||||
return (10, 9) if 'nomn' in tag.grammemes and 'Fixd' not in tag.grammemes else (8, 8)
|
|
||||||
if tag.POS in ['PRTF', 'PRTS']:
|
|
||||||
return (6, 6)
|
|
||||||
if tag.POS in ['ADJF', 'ADJS']:
|
|
||||||
return (5, 5)
|
|
||||||
if tag.POS == 'ADVB':
|
|
||||||
return (7, 4)
|
|
||||||
return (0, 0)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _choose_context_etalon(target: Morphology,
|
|
||||||
before: Optional[Collation],
|
|
||||||
after: Optional[Collation]) -> Optional[Collation]:
|
|
||||||
if not before or not before.get_morpho().can_coordinate:
|
|
||||||
return after
|
|
||||||
if not after or not after.get_morpho().can_coordinate:
|
|
||||||
return before
|
|
||||||
|
|
||||||
before_semantic = before.get_morpho().semantic
|
|
||||||
after_semantic = after.get_morpho().semantic
|
|
||||||
if target.semantic == SemanticRole.definition:
|
|
||||||
if after_semantic == SemanticRole.term:
|
|
||||||
return after
|
|
||||||
if before_semantic == SemanticRole.term:
|
|
||||||
return before
|
|
||||||
if before_semantic == SemanticRole.definition:
|
|
||||||
return before
|
|
||||||
return after
|
|
||||||
|
|
||||||
if target.semantic == SemanticRole.term:
|
|
||||||
if before_semantic == SemanticRole.definition:
|
|
||||||
return before
|
|
||||||
if after_semantic == SemanticRole.definition:
|
|
||||||
return after
|
|
||||||
|
|
||||||
return before
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _combine_morpho(target: Morphology, etalon: WordTag) -> frozenset[str]:
|
|
||||||
part_of_speech = target.tag.POS
|
|
||||||
number = etalon.number
|
|
||||||
if number == 'plur':
|
|
||||||
return frozenset([part_of_speech, number, etalon.case])
|
|
||||||
else:
|
|
||||||
gender = etalon.gender if target.semantic != SemanticRole.term else target.tag.gender
|
|
||||||
return frozenset([part_of_speech, number, gender, etalon.case])
|
|
|
@ -1,87 +0,0 @@
|
||||||
''' Russian language syntax incapsulation. '''
|
|
||||||
from __future__ import annotations
|
|
||||||
from enum import Enum, unique
|
|
||||||
|
|
||||||
from razdel import tokenize
|
|
||||||
|
|
||||||
|
|
||||||
@unique
|
|
||||||
class Capitalization(Enum):
|
|
||||||
''' Enumerating capitalization types. '''
|
|
||||||
unknwn = 0
|
|
||||||
lower_case = 1
|
|
||||||
upper_case = 2
|
|
||||||
first_capital = 3
|
|
||||||
mixed = 4
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def from_text(text: str) -> Capitalization:
|
|
||||||
''' Fabric method to identify capitalization in text. '''
|
|
||||||
if len(text) == 0:
|
|
||||||
return Capitalization.unknwn
|
|
||||||
first_capital = Capitalization._is_capital(text[0])
|
|
||||||
has_mid_capital = False
|
|
||||||
has_lower = not first_capital
|
|
||||||
for symbol in text[1:]:
|
|
||||||
if Capitalization._is_capital(symbol):
|
|
||||||
if has_lower:
|
|
||||||
return Capitalization.mixed
|
|
||||||
has_mid_capital = True
|
|
||||||
else:
|
|
||||||
if has_mid_capital:
|
|
||||||
return Capitalization.mixed
|
|
||||||
else:
|
|
||||||
has_lower = True
|
|
||||||
if has_mid_capital:
|
|
||||||
return Capitalization.upper_case
|
|
||||||
elif first_capital:
|
|
||||||
return Capitalization.first_capital
|
|
||||||
else:
|
|
||||||
return Capitalization.lower_case
|
|
||||||
|
|
||||||
def apply_to(self, text: str) -> str:
|
|
||||||
''' Apply capitalization to text. '''
|
|
||||||
if not text or self in [Capitalization.unknwn, Capitalization.mixed]:
|
|
||||||
return text
|
|
||||||
elif self == Capitalization.lower_case:
|
|
||||||
return text.lower()
|
|
||||||
elif self == Capitalization.upper_case:
|
|
||||||
return text.upper()
|
|
||||||
else:
|
|
||||||
return text[0].upper() + text[1:]
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _is_capital(symbol: str) -> bool:
|
|
||||||
return 'А' <= symbol <= 'Я' or 'A' <= symbol <= 'Z'
|
|
||||||
|
|
||||||
|
|
||||||
class RuSyntax:
|
|
||||||
''' Russian language syntax parser. '''
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def is_single_word(text: str) -> bool:
|
|
||||||
''' Test if text is a single word. '''
|
|
||||||
try:
|
|
||||||
gen = tokenize(text)
|
|
||||||
if next(gen) == '':
|
|
||||||
return True
|
|
||||||
if next(gen) == '':
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
except StopIteration:
|
|
||||||
return True
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def tokenize(text: str):
|
|
||||||
''' Split text into words. Returns list[(start, stop, text)]. '''
|
|
||||||
return tokenize(text)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def split_words(text: str) -> list[str]:
|
|
||||||
''' Split text into words. '''
|
|
||||||
return [elem.text for elem in tokenize(text)]
|
|
|
@ -1182,8 +1182,8 @@ END
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 4,9,2,1000
|
FILEVERSION 4,9,3,1000
|
||||||
PRODUCTVERSION 4,9,2,1000
|
PRODUCTVERSION 4,9,3,1000
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -1201,13 +1201,13 @@ BEGIN
|
||||||
VALUE "Comments", "Ýêñïëèêàòîð òåîðèé "
|
VALUE "Comments", "Ýêñïëèêàòîð òåîðèé "
|
||||||
VALUE "CompanyName", "ÍÏ ÖÈÂÒ ÊÎÍÖÅÏÒ"
|
VALUE "CompanyName", "ÍÏ ÖÈÂÒ ÊÎÍÖÅÏÒ"
|
||||||
VALUE "FileDescription", "Ýêñòåîð 4.9"
|
VALUE "FileDescription", "Ýêñòåîð 4.9"
|
||||||
VALUE "FileVersion", "4.9.2.1000"
|
VALUE "FileVersion", "4.9.3.1000"
|
||||||
VALUE "InternalName", "Ýêñòåîð 4.9"
|
VALUE "InternalName", "Ýêñòåîð 4.9"
|
||||||
VALUE "LegalCopyright", "Copyright © NPMP CIHT CONCEPT 1994-2024"
|
VALUE "LegalCopyright", "Copyright © NPMP CIHT CONCEPT 1994-2024"
|
||||||
VALUE "LegalTrademarks", "Ýêñòåîð™"
|
VALUE "LegalTrademarks", "Ýêñòåîð™"
|
||||||
VALUE "OriginalFilename", "Exteor.exe"
|
VALUE "OriginalFilename", "Exteor.exe"
|
||||||
VALUE "ProductName", "Ýêñòåîð 4.9"
|
VALUE "ProductName", "Ýêñòåîð 4.9"
|
||||||
VALUE "ProductVersion", "4.9.2.1000"
|
VALUE "ProductVersion", "4.9.3.1000"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
|
@ -14,8 +14,10 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] std::string Inflect(const std::string& target, const ccl::lang::Morphology& form) const override;
|
[[nodiscard]] std::string Inflect(const std::string& target, const ccl::lang::Morphology& form) const override;
|
||||||
[[nodiscard]] std::string InflectDependant(const std::string& dependant, const std::string& main) const override;
|
[[nodiscard]] std::string InflectDependant(const std::string& dependant, const std::string& main) const override;
|
||||||
[[nodiscard]] bool IsSubstr(const std::string& needle,
|
[[nodiscard]] bool IsSubstr(
|
||||||
const std::string& haystack) const override;
|
const std::string& needle,
|
||||||
|
const std::string& haystack
|
||||||
|
) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace xtr::core
|
} // namespace xtr::core
|
|
@ -60,11 +60,10 @@ Name: quicklaunchicon; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescripti
|
||||||
|
|
||||||
[Files]
|
[Files]
|
||||||
Source: "..\bin\x64\Exteor.exe"; DestDir: "{app}"; Flags: ignoreversion
|
Source: "..\bin\x64\Exteor.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
Source: "..\import\cctext\*"; DestDir: "{app}\cctext"; Flags: ignoreversion
|
|
||||||
Source: "app\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs
|
Source: "app\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs
|
||||||
Source: "..\distr\app\DejaVu Sans.ttf"; DestDir: "{app}"; Flags: ignoreversion
|
Source: "..\distr\app\DejaVu Sans.ttf"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
|
|
||||||
Source: "..\script\PymorphyInstall.bat"; DestDir: {tmp}; Flags: deleteafterinstall
|
Source: "..\script\installDependencies.bat"; DestDir: {tmp}; Flags: deleteafterinstall
|
||||||
|
|
||||||
[Icons]
|
[Icons]
|
||||||
Name: "{group}\{#ExteorName}"; Filename: "{app}\{#ExteorEXE}"
|
Name: "{group}\{#ExteorName}"; Filename: "{app}\{#ExteorEXE}"
|
||||||
|
@ -101,7 +100,7 @@ Filename: "{app}\{#ExteorEXE}"; Description: "{cm:LaunchProgram,{#StringChange(E
|
||||||
Filename: "{app}\Документация\README.rtf"; Description: "{cm:ReadMe}"; Flags: nowait postinstall skipifsilent unchecked shellexec
|
Filename: "{app}\Документация\README.rtf"; Description: "{cm:ReadMe}"; Flags: nowait postinstall skipifsilent unchecked shellexec
|
||||||
Filename: "{tmp}\{#VSRedist}"; Parameters: "/install /quiet /NORESTART"; StatusMsg: {cm:CppRedist}; Check: VCRedistNeedsInstall()
|
Filename: "{tmp}\{#VSRedist}"; Parameters: "/install /quiet /NORESTART"; StatusMsg: {cm:CppRedist}; Check: VCRedistNeedsInstall()
|
||||||
Filename: "{tmp}\{#PythonRedist}"; Parameters: "/quiet InstallAllUsers=1 PrependPath=1 Include_test=0"; StatusMsg: {cm:PythonInstall}; Check: PythonNeedsInstall()
|
Filename: "{tmp}\{#PythonRedist}"; Parameters: "/quiet InstallAllUsers=1 PrependPath=1 Include_test=0"; StatusMsg: {cm:PythonInstall}; Check: PythonNeedsInstall()
|
||||||
Filename: "{tmp}\PymorphyInstall.bat"; Parameters: """{code:PythonPath}"""
|
Filename: "{tmp}\installDependencies.bat"; Parameters: """{code:PythonPath}"""
|
||||||
|
|
||||||
[Code]
|
[Code]
|
||||||
function IsPythonMissing: Boolean; forward;
|
function IsPythonMissing: Boolean; forward;
|
||||||
|
|
|
@ -60,11 +60,10 @@ Name: quicklaunchicon; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescripti
|
||||||
|
|
||||||
[Files]
|
[Files]
|
||||||
Source: "..\bin\x64\Exteor.exe"; DestDir: "{app}"; Flags: ignoreversion
|
Source: "..\bin\x64\Exteor.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
Source: "..\import\cctext\*"; DestDir: "{app}\cctext"; Flags: ignoreversion
|
|
||||||
Source: "app\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs
|
Source: "app\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs
|
||||||
Source: "..\distr\app\DejaVu Sans.ttf"; DestDir: "{app}"; Flags: ignoreversion
|
Source: "..\distr\app\DejaVu Sans.ttf"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
|
|
||||||
Source: "..\script\PymorphyInstall.bat"; DestDir: {tmp}; Flags: deleteafterinstall
|
Source: "..\script\installDependencies.bat"; DestDir: {tmp}; Flags: deleteafterinstall
|
||||||
|
|
||||||
[Icons]
|
[Icons]
|
||||||
Name: "{group}\{#ExteorName}"; Filename: "{app}\{#ExteorEXE}"
|
Name: "{group}\{#ExteorName}"; Filename: "{app}\{#ExteorEXE}"
|
||||||
|
@ -101,7 +100,7 @@ Filename: "{app}\{#ExteorEXE}"; Description: "{cm:LaunchProgram,{#StringChange(E
|
||||||
Filename: "{app}\Документация\README.rtf"; Description: "{cm:ReadMe}"; Flags: nowait postinstall skipifsilent unchecked shellexec
|
Filename: "{app}\Документация\README.rtf"; Description: "{cm:ReadMe}"; Flags: nowait postinstall skipifsilent unchecked shellexec
|
||||||
Filename: "{tmp}\{#VSRedist}"; Parameters: "/install /quiet /NORESTART"; StatusMsg: {cm:CppRedist}; Check: VCRedistNeedsInstall()
|
Filename: "{tmp}\{#VSRedist}"; Parameters: "/install /quiet /NORESTART"; StatusMsg: {cm:CppRedist}; Check: VCRedistNeedsInstall()
|
||||||
Filename: "{tmp}\{#PythonRedist}"; Parameters: "/quiet InstallAllUsers=1 PrependPath=1 Include_test=0"; StatusMsg: {cm:PythonInstall}; Check: PythonNeedsInstall()
|
Filename: "{tmp}\{#PythonRedist}"; Parameters: "/quiet InstallAllUsers=1 PrependPath=1 Include_test=0"; StatusMsg: {cm:PythonInstall}; Check: PythonNeedsInstall()
|
||||||
Filename: "{tmp}\PymorphyInstall.bat"; Parameters: """{code:PythonPath}"""
|
Filename: "{tmp}\installDependencies.bat"; Parameters: """{code:PythonPath}"""
|
||||||
|
|
||||||
[Code]
|
[Code]
|
||||||
function IsPythonMissing: Boolean; forward;
|
function IsPythonMissing: Boolean; forward;
|
||||||
|
|
|
@ -7,8 +7,7 @@ PING -n 1 www.google.com > nul && (goto :SUCCESS) || (goto :FAILURE)
|
||||||
|
|
||||||
:SUCCESS
|
:SUCCESS
|
||||||
@echo off
|
@echo off
|
||||||
"%python3Path%Scripts\pip.exe" install razdel || (goto :FAILURE)
|
"%python3Path%Scripts\pip.exe" install cctext || (goto :FAILURE)
|
||||||
"%python3Path%Scripts\pip.exe" install pymorphy3 || (goto :FAILURE)
|
|
||||||
goto :END
|
goto :END
|
||||||
|
|
||||||
:FAILURE
|
:FAILURE
|
|
@ -151,26 +151,35 @@ void PyCore::Stop() noexcept {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PyCore::LoadModule(const std::string& moduleName, const std::string& pyFileName) {
|
bool PyCore::LoadModule(const std::string& moduleName, const std::string& pyImport) {
|
||||||
if (!IsRunning()) {
|
if (!IsRunning()) {
|
||||||
return false;
|
return false;
|
||||||
} else if (moduleName.empty()) {
|
} else if (moduleName.empty()) {
|
||||||
return false;
|
return false;
|
||||||
} else if (modules.contains(moduleName)) {
|
} else if (modules.contains(moduleName)) {
|
||||||
return true;
|
return true;
|
||||||
} else if (auto nameObj = Object::FromNew(PyUnicode_FromString(pyFileName.c_str()));
|
}
|
||||||
nameObj == nullptr) {
|
|
||||||
|
auto nameObj = Object::FromNew(PyUnicode_FromString(pyImport.c_str()));
|
||||||
|
if (nameObj == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
} else if (auto moduleObj = Object::FromNew(PyImport_Import(nameObj.get()));
|
|
||||||
moduleObj == nullptr) {
|
|
||||||
return false;
|
|
||||||
} else if (auto dictionaryObj = Object::FromBorrowed(PyModule_GetDict(moduleObj.get()));
|
|
||||||
dictionaryObj == nullptr) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
modules.insert(std::pair(moduleName, Module{ .pyModule = moduleObj, .pyDictionary = std::move(dictionaryObj) }));
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto moduleObj = Object::FromNew(PyImport_Import(nameObj.get()));
|
||||||
|
if (moduleObj == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto dictionaryObj = Object::FromBorrowed(PyModule_GetDict(moduleObj.get()));
|
||||||
|
if (dictionaryObj == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
modules.insert(std::pair(
|
||||||
|
moduleName,
|
||||||
|
Module{ .pyModule = moduleObj, .pyDictionary = std::move(dictionaryObj) }
|
||||||
|
));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Callable PyCore::PyFunction(const std::string& moduleName, const std::string& funcName) const {
|
Callable PyCore::PyFunction(const std::string& moduleName, const std::string& funcName) const {
|
||||||
|
|
|
@ -154,7 +154,7 @@
|
||||||
<WarningLevel>Level4</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<ObjectFileName>$(IntDir)obj\</ObjectFileName>
|
<ObjectFileName>$(IntDir)obj\</ObjectFileName>
|
||||||
<AdditionalIncludeDirectories>Mock;./;..\include;..\import\include;..\..\ConceptCore\output\include;..\..\OfficeOLE\include;C:\Program Files (x86)\Python312-32\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>Mock;./;..\include;..\import\include;..\..\GH-ConceptCore\output\include;..\..\OfficeOLE\include;C:\Program Files (x86)\Python312-32\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||||
<BuildStlModules>false</BuildStlModules>
|
<BuildStlModules>false</BuildStlModules>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -163,12 +163,11 @@
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<AdditionalDependencies>ConceptCoreLibraryd.lib;RSlangd.lib;cclGraphd.lib;cclLangd.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>ConceptCoreLibraryd.lib;RSlangd.lib;cclGraphd.lib;cclLangd.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||||
<AdditionalLibraryDirectories>C:\Program Files (x86)\Python312-32\libs;..\..\ConceptCore\output\lib\x86;..\..\OfficeOLE\output\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>C:\Program Files (x86)\Python312-32\libs;..\..\GH-ConceptCore\output\lib\x86;..\..\OfficeOLE\output\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
|
||||||
</Link>
|
</Link>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Command>xcopy /y /s /q /i "..\import\cctext" "$(OutDir)\cctext\"
|
<Command>copy "Data\sample_module.py" "$(OutDir)sample_module.py"
|
||||||
copy "Data\sample_module.py" "$(OutDir)sample_module.py"
|
|
||||||
copy "C:\Program Files (x86)\Python312-32\Python312_d.dll" "$(OutDir)"
|
copy "C:\Program Files (x86)\Python312-32\Python312_d.dll" "$(OutDir)"
|
||||||
copy "C:\Program Files (x86)\Python312-32\Python312_d.pdb" "$(OutDir)"</Command>
|
copy "C:\Program Files (x86)\Python312-32\Python312_d.pdb" "$(OutDir)"</Command>
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
|
@ -184,7 +183,7 @@ copy "C:\Program Files (x86)\Python312-32\Python312_d.pdb" "$(OutDir)"</Command>
|
||||||
<WarningLevel>Level4</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<ObjectFileName>$(IntDir)obj\</ObjectFileName>
|
<ObjectFileName>$(IntDir)obj\</ObjectFileName>
|
||||||
<AdditionalIncludeDirectories>Mock;./;..\include;..\header;..\import\include;..\..\ConceptCore\output\include;..\..\OfficeOLE\include;C:\Program Files\Python312\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>Mock;./;..\include;..\header;..\import\include;..\..\GH-ConceptCore\output\include;..\..\OfficeOLE\include;C:\Program Files\Python312\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||||
<BuildStlModules>false</BuildStlModules>
|
<BuildStlModules>false</BuildStlModules>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -193,12 +192,11 @@ copy "C:\Program Files (x86)\Python312-32\Python312_d.pdb" "$(OutDir)"</Command>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<AdditionalDependencies>ConceptCoreLibraryd.lib;RSlangd.lib;cclGraphd.lib;cclLangd.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>ConceptCoreLibraryd.lib;RSlangd.lib;cclGraphd.lib;cclLangd.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||||
<AdditionalLibraryDirectories>C:\Program Files\Python312\libs;..\..\ConceptCore\output\lib\x64;..\..\OfficeOLE\output\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>C:\Program Files\Python312\libs;..\..\GH-ConceptCore\output\lib\x64;..\..\OfficeOLE\output\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
|
||||||
</Link>
|
</Link>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Command>xcopy /y /s /q /i "..\import\cctext" "$(OutDir)\cctext\"
|
<Command>copy "Data\sample_module.py" "$(OutDir)sample_module.py"</Command>
|
||||||
copy "Data\sample_module.py" "$(OutDir)sample_module.py"</Command>
|
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
@ -212,7 +210,7 @@ copy "Data\sample_module.py" "$(OutDir)sample_module.py"</Command>
|
||||||
<TreatWarningAsError>false</TreatWarningAsError>
|
<TreatWarningAsError>false</TreatWarningAsError>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<ObjectFileName>$(IntDir)obj\</ObjectFileName>
|
<ObjectFileName>$(IntDir)obj\</ObjectFileName>
|
||||||
<AdditionalIncludeDirectories>Mock;./;..\include;..\header;..\import\include;..\import\include;..\..\ConceptCore\output\include;..\..\OfficeOLE\include;C:\Program Files (x86)\Python312-32\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>Mock;./;..\include;..\header;..\import\include;..\import\include;..\..\GH-ConceptCore\output\include;..\..\OfficeOLE\include;C:\Program Files (x86)\Python312-32\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||||
<BuildStlModules>false</BuildStlModules>
|
<BuildStlModules>false</BuildStlModules>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -223,12 +221,11 @@ copy "Data\sample_module.py" "$(OutDir)sample_module.py"</Command>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<AdditionalDependencies>ConceptCoreLibrary.lib;RSlang.lib;cclGraph.lib;cclLang.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>ConceptCoreLibrary.lib;RSlang.lib;cclGraph.lib;cclLang.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||||
<AdditionalLibraryDirectories>C:\Program Files (x86)\Python312-32\libs;..\..\ConceptCore\output\lib\x86;..\..\OfficeOLE\output\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>C:\Program Files (x86)\Python312-32\libs;..\..\GH-ConceptCore\output\lib\x86;..\..\OfficeOLE\output\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
|
||||||
</Link>
|
</Link>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Command>xcopy /y /s /q /i "..\import\cctext" "$(OutDir)\cctext\"
|
<Command>copy "Data\sample_module.py" "$(OutDir)sample_module.py"
|
||||||
copy "Data\sample_module.py" "$(OutDir)sample_module.py"
|
|
||||||
copy "C:\Program Files (x86)\Python312-32\Python312.dll" "$(OutDir)"
|
copy "C:\Program Files (x86)\Python312-32\Python312.dll" "$(OutDir)"
|
||||||
copy "C:\Program Files (x86)\Python312-32\Python312.pdb" "$(OutDir)"</Command>
|
copy "C:\Program Files (x86)\Python312-32\Python312.pdb" "$(OutDir)"</Command>
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
|
@ -244,7 +241,7 @@ copy "C:\Program Files (x86)\Python312-32\Python312.pdb" "$(OutDir)"</Command>
|
||||||
<TreatWarningAsError>false</TreatWarningAsError>
|
<TreatWarningAsError>false</TreatWarningAsError>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<ObjectFileName>$(IntDir)obj\</ObjectFileName>
|
<ObjectFileName>$(IntDir)obj\</ObjectFileName>
|
||||||
<AdditionalIncludeDirectories>Mock;./;..\include;..\header;..\import\include;..\import\include;..\..\ConceptCore\output\include;..\..\OfficeOLE\include;C:\Program Files\Python312\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>Mock;./;..\include;..\header;..\import\include;..\import\include;..\..\GH-ConceptCore\output\include;..\..\OfficeOLE\include;C:\Program Files\Python312\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||||
<BuildStlModules>false</BuildStlModules>
|
<BuildStlModules>false</BuildStlModules>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -256,12 +253,11 @@ copy "C:\Program Files (x86)\Python312-32\Python312.pdb" "$(OutDir)"</Command>
|
||||||
<AdditionalDependencies>ConceptCoreLibrary.lib;RSlang.lib;cclGraph.lib;cclLang.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>ConceptCoreLibrary.lib;RSlang.lib;cclGraph.lib;cclLang.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||||
<AdditionalLibraryDirectories>C:\Program Files\Python312\libs;..\..\ConceptCore\output\lib\x64;..\..\OfficeOLE\output\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>C:\Program Files\Python312\libs;..\..\GH-ConceptCore\output\lib\x64;..\..\OfficeOLE\output\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
|
||||||
</Link>
|
</Link>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Command>xcopy /y /s /q /i "..\import\cctext" "$(OutDir)\cctext\"
|
<Command>copy "Data\sample_module.py" "$(OutDir)sample_module.py"</Command>
|
||||||
copy "Data\sample_module.py" "$(OutDir)sample_module.py"</Command>
|
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
|
|
|
@ -20,8 +20,9 @@ protected:
|
||||||
std::unique_ptr<PyTextProcessor> processor{ nullptr };
|
std::unique_ptr<PyTextProcessor> processor{ nullptr };
|
||||||
|
|
||||||
void SetUp() override {
|
void SetUp() override {
|
||||||
ASSERT_TRUE(python.Start());
|
static CString path{ "C:\\Program Files\\Python312\\" };
|
||||||
python.LoadModule("cctext", "cctext");
|
ASSERT_TRUE(python.Start(path));
|
||||||
|
ASSERT_TRUE(python.LoadModule("cctext", "cctext"));
|
||||||
processor = std::make_unique<PyTextProcessor>();
|
processor = std::make_unique<PyTextProcessor>();
|
||||||
processor->InitModule("cctext");
|
processor->InitModule("cctext");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user