mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 04:50:36 +03:00
Extract cctext as independant library and update deps
This commit is contained in:
parent
12dfd1c3cb
commit
9db4ee4d56
|
@ -94,8 +94,7 @@ This readme file is used mostly to document project dependencies
|
|||
- gunicorn
|
||||
- coreapi
|
||||
- psycopg2-binary
|
||||
- pymorphy3
|
||||
- razdel
|
||||
- cctext
|
||||
</pre>
|
||||
</details>
|
||||
<details>
|
||||
|
|
|
@ -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 and natasha libraries. '''
|
||||
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)]
|
|
@ -1,8 +0,0 @@
|
|||
''' Tests. '''
|
||||
from .t_reference import *
|
||||
from .t_ruparser import *
|
||||
from .t_syntax import *
|
||||
from .t_conceptapi import *
|
||||
from .t_rumodel import *
|
||||
from .t_context import *
|
||||
from .t_resolver import *
|
File diff suppressed because it is too large
Load Diff
|
@ -1,866 +0,0 @@
|
|||
тектологические состояния
|
||||
первые здания
|
||||
доска
|
||||
структуры
|
||||
тектологические состояния
|
||||
тектологические переходы
|
||||
уникомплексные тектологические переходы
|
||||
поликомплексные переходы
|
||||
процессы
|
||||
разрушаемые оружием структуры
|
||||
создаваемые оружием структуры
|
||||
неразрушаемые оружием структуры
|
||||
несоздаваемые оружием структуры
|
||||
формы движения
|
||||
объекты
|
||||
систенты
|
||||
субъекты
|
||||
системные классы
|
||||
системные субъекты
|
||||
системное сознание
|
||||
системно познаные объекты
|
||||
обсубъект
|
||||
системно непознанные объекты
|
||||
оценки
|
||||
шкала оценок
|
||||
альтернативы
|
||||
критерии
|
||||
сеть альтернатив
|
||||
предъявление
|
||||
субъект актуализации
|
||||
основание
|
||||
актуализированная альтернатива
|
||||
цепи актуализаций
|
||||
Сечения актуализации
|
||||
комплексы
|
||||
квазиконфликтанты
|
||||
консистенции
|
||||
квазиконфликтантные комплексы
|
||||
коструктурный слой
|
||||
коструктурное окружение
|
||||
квазиконфликты
|
||||
шкалы оценок квазиконфликтанта
|
||||
ущемленная сторона конфликтного перехода
|
||||
кооперативный переход
|
||||
конфликты
|
||||
консистенты
|
||||
цепи нагнетания напряженности
|
||||
состояние напряженности
|
||||
конфликтное состояние
|
||||
структурный дифференциал
|
||||
конфликтоген
|
||||
основание конфликта
|
||||
конфликтанты
|
||||
Уникомплексный переход
|
||||
структурный дифференциал перехода
|
||||
рабочий процесс оружия
|
||||
приемы
|
||||
натуральные числа
|
||||
складские операции
|
||||
группа организационных единиц
|
||||
полные описания издений
|
||||
разбиения
|
||||
номера договорных поставок
|
||||
номера приходных ордеров поставок
|
||||
дни приходных ордеров поставок
|
||||
дни
|
||||
выбранное число
|
||||
организационные единицы
|
||||
изделия
|
||||
операции
|
||||
группа организаций
|
||||
предприятия
|
||||
организация
|
||||
склад
|
||||
отрезки времени
|
||||
прошлые состояния склада
|
||||
подразделения
|
||||
поступления партий изделий
|
||||
отпуск партий изделий
|
||||
типы изделий
|
||||
виды изделий
|
||||
договорные поставки
|
||||
поставки
|
||||
начальные отрезки натуральных чисел
|
||||
абсолютные нумерации разбиений
|
||||
относительные нумерации разбиений
|
||||
календари
|
||||
солнечные календари
|
||||
григорианские календари
|
||||
квартальные григорианские календари
|
||||
календарные годы
|
||||
календарные кварталы
|
||||
отрезки нумерации складских операций
|
||||
поступление
|
||||
отпуск
|
||||
классы изделий
|
||||
текущее состояние склада
|
||||
спецификация
|
||||
единицы учета, заданные спецификациями изделий
|
||||
Единицы учета, заданные множествами изделий
|
||||
единицы учета
|
||||
прием партий изделий
|
||||
отпуск изделий
|
||||
характеристики
|
||||
единицы измерения
|
||||
числовые индексы
|
||||
полные описания изделий
|
||||
полные описания
|
||||
самое мелкое разбиение
|
||||
самое крупное разбиение
|
||||
виды операций
|
||||
Складские операции, выраженные в единицах учета
|
||||
Поступления изделий, выраженные в единицах учета
|
||||
Отпуск изделий, выраженный в единицах учета
|
||||
високосные годы
|
||||
невисокосные годы
|
||||
годы
|
||||
месяцы
|
||||
кварталы
|
||||
номера фондовых извещений
|
||||
номера договоров
|
||||
фондовые извещения
|
||||
Нумерация складских операций
|
||||
фонды
|
||||
договора
|
||||
дата
|
||||
номер приходного ордера
|
||||
поставки по техпомощи
|
||||
Тезаурус кафедры КАиП:
|
||||
Н-арное отношение
|
||||
Н-местное отношение
|
||||
R-интерпретация
|
||||
Абельность
|
||||
Абсолютное дополнение
|
||||
Абстрагирование
|
||||
Абстрактная система
|
||||
Абстрактный процесс
|
||||
Абстракция
|
||||
Автоматизированная система проектирования систем организационного управления
|
||||
Адаптивная система
|
||||
Адекватность
|
||||
Аксиома
|
||||
Аксиома связности
|
||||
Аксиома структуры
|
||||
Аксиоматизация
|
||||
Аксиоматика теории
|
||||
Аксиоматическая теория
|
||||
Аксиомы группы
|
||||
Аксиомы синтеза
|
||||
Актуальность
|
||||
Алгебраическая структура
|
||||
Алгебра конструктов
|
||||
Альтернатива
|
||||
Альтернативные методы
|
||||
Анализ
|
||||
Аналитическая теория
|
||||
Аналогия
|
||||
Аспект
|
||||
Аспектная теория
|
||||
АСП СОУ
|
||||
АТ
|
||||
Атрибут
|
||||
Атрибутивная форма
|
||||
Атрибутивное мышление
|
||||
База данных
|
||||
Базис множеств
|
||||
Базисное множество
|
||||
Библиотека моделей
|
||||
Бинарная операция
|
||||
Бинарное отношение
|
||||
Богданов
|
||||
Большая проекция
|
||||
Боулдинг
|
||||
Булеан
|
||||
Бурбаки
|
||||
Вершина
|
||||
Взаимно дополнительные теории
|
||||
Видообразование
|
||||
Включение
|
||||
Власть
|
||||
Внешность предметной области
|
||||
Внутренние термы ядра теории
|
||||
Возможность
|
||||
Восхождение
|
||||
Вспомогательные базисные множества
|
||||
Вторичная функция
|
||||
Вторичный метод
|
||||
Вход
|
||||
Вход процесса
|
||||
Выбор
|
||||
Выразимость
|
||||
Выразительная сила
|
||||
Выразительные средства теории
|
||||
Высказывание
|
||||
Выход
|
||||
Выход процесса
|
||||
ГДМ
|
||||
Генезис
|
||||
Гипертеория
|
||||
Гипотеза
|
||||
Гипотетико-дедуктивные требования
|
||||
Гипотетико-дедуктивный метод
|
||||
Главная функция
|
||||
Глубина проникновения
|
||||
Гносеология
|
||||
Гомоморфизм
|
||||
ГП РС
|
||||
Границы сети процессов
|
||||
Граф
|
||||
Граф термов
|
||||
Группа
|
||||
Двухместное отношение
|
||||
Дебуленизация
|
||||
Дедуктивная теория
|
||||
Декартово произведение
|
||||
Декомпозиция
|
||||
Дескриптивное использование теории
|
||||
Дескриптивный подход
|
||||
Диаграмма Венна
|
||||
Динамическая система
|
||||
Дихотомия
|
||||
Доказательство
|
||||
Дуга
|
||||
Желаемая система
|
||||
Жизненный цикл
|
||||
Жизненный цикл интереса
|
||||
Жизненный цикл угрозы
|
||||
Зависимое множество аксиом
|
||||
Задача
|
||||
Закон композиции
|
||||
Знаковая система
|
||||
Идентификация
|
||||
Идеолог
|
||||
Идея
|
||||
Идея абстрактного выбора
|
||||
Иерархическая структура
|
||||
Измельчение графа термов
|
||||
Изменение
|
||||
Изоморфизм
|
||||
Изофункциональные методы
|
||||
Ильковский
|
||||
Имплицитная форма
|
||||
Интегрированные объекты
|
||||
Интенсионализация
|
||||
Интересы
|
||||
Интерпретант
|
||||
Интерпретатор
|
||||
Интерпретация
|
||||
Интерпретированная теория
|
||||
Информационная система
|
||||
Инцесс
|
||||
Инцессант
|
||||
Искусственная система
|
||||
Исследовательский подход
|
||||
Истинное подмножество
|
||||
Исток графа термов
|
||||
Исходная сущность
|
||||
Исходное отношение
|
||||
Исходное понятие
|
||||
Исходное утверждение
|
||||
КА
|
||||
КАК-ориентированная система
|
||||
КАНС
|
||||
Карта понятий
|
||||
Картезиан
|
||||
Каталог методов
|
||||
Категорическая теория
|
||||
Качественная проблема
|
||||
Качественные характеристики теории
|
||||
Квазиаксиома
|
||||
Классификация
|
||||
Классификация множества объектов
|
||||
Классы концептуальных схем
|
||||
Классы систем
|
||||
Класс эквивалентности
|
||||
Количественная проблема
|
||||
Комплексное управление развитием систем
|
||||
Композиция
|
||||
Композиция-2
|
||||
Конвенция
|
||||
Конкрест
|
||||
Конкретант
|
||||
Конкретизация
|
||||
Конкретор
|
||||
Конкреция
|
||||
Конституента
|
||||
Конструкт
|
||||
Конструкт-конструктные конструкции
|
||||
Конструкт-содержантные конструкции
|
||||
Конструкция
|
||||
Концепт
|
||||
Концептуализация
|
||||
Концептуализм
|
||||
Концептуальная конструкция
|
||||
Концептуальная модель
|
||||
Концептуальная схема
|
||||
Концептуальное мышление
|
||||
Концептуальное проектирование
|
||||
Концептуальный анализ
|
||||
Концептуальный анализ и синтез
|
||||
Концептуальный аппарат
|
||||
Корректировка целей
|
||||
Кортеж
|
||||
КП
|
||||
Критерий
|
||||
Критический элемент
|
||||
Круги Эйлера
|
||||
КС
|
||||
КТО-ориентированная система
|
||||
КУРС
|
||||
Лингвистическая интерпретация
|
||||
Логика
|
||||
Логические средства
|
||||
Логическое мышление
|
||||
ЛПР
|
||||
Максимальное измельчение
|
||||
МАКС система
|
||||
Малая проекция
|
||||
Математическая структура
|
||||
Математическая теория
|
||||
Математические средства КП СОУ
|
||||
Материальная интерпретация
|
||||
Машинные средства КП СОУ
|
||||
М-граф
|
||||
Мегатеория
|
||||
Мезотеория
|
||||
Меновая власть
|
||||
Мероприятия по достижению частных целей
|
||||
Метатеорема
|
||||
Метатеория
|
||||
Метаязык
|
||||
Метод
|
||||
Метод КП СОУ
|
||||
Методология
|
||||
Механизм
|
||||
Механизм парирования угрозы
|
||||
Микротеория
|
||||
Минимальный род структуры
|
||||
Множество
|
||||
Множество сечений
|
||||
Множество-степень
|
||||
Модель
|
||||
Модель желаемого выхода
|
||||
Морфологическое отношение
|
||||
Мощность множества
|
||||
Мультиграф
|
||||
Мышление
|
||||
Нагрузка
|
||||
Надпроцесс
|
||||
Надсистема
|
||||
Направления развёртывания
|
||||
Н-арное отношение
|
||||
Независимое множество аксиом
|
||||
Непересекающиеся множества
|
||||
Непротиворечивая теория
|
||||
Нереализованные функции
|
||||
Несовместная теория
|
||||
Неформальная аксиоматическая теория
|
||||
Нижнее замыкание вершины графа
|
||||
Н-местное отношение
|
||||
Нормативная методология
|
||||
Нормативная теория
|
||||
Нормативное мышление
|
||||
Нормативный подход
|
||||
Область значений
|
||||
Область определения
|
||||
Область отправления
|
||||
Область прибытия
|
||||
Обратная связь
|
||||
Обстоятельства
|
||||
Общая теория систем
|
||||
Общезначимая формула
|
||||
Объединение
|
||||
Объект
|
||||
Объектная регламентация
|
||||
Объектные теории
|
||||
Объект управления
|
||||
Объём теории
|
||||
Объяснительная теория
|
||||
Объясняемая теория
|
||||
Ограничение
|
||||
Онтологизация
|
||||
Онтология
|
||||
Оператор
|
||||
Операции КАНС
|
||||
Операциональная схема синтеза
|
||||
Операциональное понятие
|
||||
Операция
|
||||
Операция малая проекция
|
||||
Операция повышения размерности
|
||||
Определяющее свойство множества
|
||||
Оптимизация
|
||||
Организационное управление
|
||||
Организация
|
||||
Ориентированный путь
|
||||
Основание классификации
|
||||
Отвлечённые теории
|
||||
Открытая система
|
||||
Относительное дополнение
|
||||
Отношение
|
||||
Отношение порядка
|
||||
Отношение эквивалентности
|
||||
Отображение
|
||||
Отождествление
|
||||
Отрицание множества
|
||||
ОТСУ
|
||||
ПВР
|
||||
Первичная функция
|
||||
Первичные термины теории
|
||||
Перепостулирование
|
||||
Пересекающиеся множества
|
||||
Пересечение множеств
|
||||
Петля
|
||||
ПО
|
||||
Поддержание
|
||||
Подмножество
|
||||
Подсистема
|
||||
Подтеория
|
||||
Подфункция
|
||||
Политика
|
||||
Полифункциональные методы
|
||||
Полная согласованная интерпретация
|
||||
Полная теория
|
||||
Полный вход
|
||||
Полный выход
|
||||
Понятие
|
||||
Порождающие структуры
|
||||
Постулирование
|
||||
Потенциальная связь
|
||||
Потенциально связанные процессы
|
||||
Потенциальный критический элемент системы
|
||||
Предмет
|
||||
Предметная область
|
||||
Предметный язык
|
||||
Предположение
|
||||
Преобразование
|
||||
Препятствие
|
||||
Прескриптивное использование теории
|
||||
Прескриптивный подход
|
||||
Приложение теории
|
||||
Принадлежность
|
||||
Принцип дополнительности
|
||||
ПРО
|
||||
Проблема
|
||||
Прогнозный сценарий
|
||||
Проект
|
||||
Проектирование СОУ
|
||||
Проектный подход
|
||||
Проект СОУ
|
||||
Проекция родовой структуры
|
||||
Произведение множеств
|
||||
Производное понятие
|
||||
Производные понятия n-го ранга
|
||||
Производные термы
|
||||
Противоречивая теория
|
||||
Процесс
|
||||
Процесс КП конкретной СОУ
|
||||
Процесс ограничения
|
||||
Процессор
|
||||
Процесс с необеспеченными связями
|
||||
Процесс с ролевыми отношениями
|
||||
ПРС
|
||||
ПТ
|
||||
Пустое множество
|
||||
Разбиение множества объектов
|
||||
Разбиение множества объектов по явному основанию
|
||||
Развёрнутое графовое представление
|
||||
Развёрнутый род структуры
|
||||
Развёртывание теории
|
||||
Развивающаяся система
|
||||
Развитие
|
||||
Разнообразие
|
||||
Ранг
|
||||
Ранжирование
|
||||
Расчленённые множества
|
||||
Редукционизм
|
||||
Редукция
|
||||
Реконструкция
|
||||
Ресурс
|
||||
Рефлексивное отношение
|
||||
Решение
|
||||
Р-интерпретация
|
||||
Родовая структура
|
||||
Родовое отношение
|
||||
Родоструктурная экспликация
|
||||
Род структуры
|
||||
Рост
|
||||
Рутинная операция
|
||||
СА
|
||||
Самоорганизующаяся система
|
||||
САПР
|
||||
Свободное мышление
|
||||
Свойство
|
||||
Свойство икса
|
||||
Связь
|
||||
Семантическая сеть
|
||||
Сеть
|
||||
Сеть ПРО
|
||||
Сеть процессов
|
||||
Сеть процессов с ролевыми отношениями
|
||||
Сеть частных целей
|
||||
Сечение
|
||||
Сильные и слабые формы концептуализации
|
||||
Симметричное отношение
|
||||
Синтаксический язык
|
||||
Синтез
|
||||
Синтез родов структур
|
||||
С-интерпретация
|
||||
Система
|
||||
Система автоматизированного проектирования
|
||||
Система восстановления
|
||||
Система организационного управления
|
||||
Система поддержания
|
||||
Система процессов
|
||||
Система развития
|
||||
Система стратегического планирования
|
||||
Система стратегического управления
|
||||
Система управления базами данных
|
||||
Система функционирования
|
||||
Системные классы
|
||||
Системные объекты
|
||||
Системный анализ
|
||||
Слабоструктурированная проблема
|
||||
Словесная форма
|
||||
Сложная система
|
||||
Сложная структура
|
||||
Событие
|
||||
Совершенствование
|
||||
Совместимая теория
|
||||
Содержание
|
||||
Содержант
|
||||
Содержательно-дедуктивное развёртывание
|
||||
Соединение
|
||||
Соединение множеств
|
||||
Соискатель ресурсов
|
||||
Соответствие
|
||||
Состояние организации
|
||||
СОУ
|
||||
Сравнение
|
||||
Среда
|
||||
Средства КП СОУ
|
||||
Срез графа термов
|
||||
Срез подграфа термов
|
||||
Сток графа термов
|
||||
Стратегические цели
|
||||
Стратегическое планирование
|
||||
Стратегическое состояние
|
||||
Стратегия
|
||||
Стратификация
|
||||
Строгое включение
|
||||
Структ
|
||||
Структура
|
||||
Структура, определённая отношением порядка
|
||||
Ступень
|
||||
СУБД
|
||||
Субъект
|
||||
Субъектная регламентация
|
||||
Субъект целеполагания
|
||||
Сумма
|
||||
Сущность
|
||||
Схема
|
||||
Схематизация
|
||||
Творческая операция
|
||||
Тектология
|
||||
Тело теории
|
||||
Теорема
|
||||
Теоретико-множественная интерпретация
|
||||
Теоретико-множественная экспликация
|
||||
Теоретико-множественные операции
|
||||
Теоретико-системная экспликация
|
||||
Теоретико-системное мышление
|
||||
Теоретическое описание объекта
|
||||
Теория
|
||||
Теория множеств
|
||||
Теория систем
|
||||
Терм
|
||||
Терминальная теория
|
||||
Терм-функция
|
||||
Термы n-го ранга
|
||||
Техническая система
|
||||
Техногенема n-го порядка
|
||||
Технология КП СОУ
|
||||
Типизация
|
||||
Типология
|
||||
Типы мышления
|
||||
ТМИ
|
||||
ТМФ
|
||||
Толчок Ильковского
|
||||
Топология
|
||||
Точка зрения
|
||||
Транзитивное отношение
|
||||
Требование проблемы
|
||||
Требования к проекту СОУ
|
||||
Треугольник Фреге
|
||||
ТСК
|
||||
Угроза
|
||||
Универсальное множество
|
||||
Универсум
|
||||
Упорядоченная n-ка
|
||||
Упорядоченная пара
|
||||
Управление
|
||||
Управление процессом достижения цели
|
||||
Урманцев
|
||||
Уровень эксплицитности
|
||||
Условие проблемы
|
||||
Фактормножество
|
||||
Фактор-структура
|
||||
Фактор-структура n-го ранга
|
||||
Феноменология
|
||||
Формализация
|
||||
Формальная система
|
||||
Формальная теория
|
||||
Формально-дедуктивное развёртывание
|
||||
Формальное мышление
|
||||
Форма от x
|
||||
Формы концептуализации
|
||||
Формы мышления
|
||||
Функционально-методное отношение
|
||||
Функциональные свойства
|
||||
Функционирование
|
||||
Функция
|
||||
Целевой выход
|
||||
Целевой терм
|
||||
Целенаправленная система
|
||||
Целенаправленная система с ОС
|
||||
Целеустремлённая система
|
||||
Цель
|
||||
Цикл
|
||||
ЦНС
|
||||
Частная цель
|
||||
Член множества
|
||||
Членство
|
||||
Шкала множеств
|
||||
Шкала ступеней
|
||||
Эквивалентность
|
||||
Экспликация
|
||||
Эксплицитное мышление
|
||||
Экстенсионализация
|
||||
Элемент
|
||||
Элементарная теория
|
||||
Элементарный объект
|
||||
Элемент входа
|
||||
Элемент выхода
|
||||
Эмпирический материал
|
||||
Эпистемология
|
||||
Этапы разработки концептуальной схемы
|
||||
Этиология
|
||||
Ядро
|
||||
Язык-объект
|
||||
Ярус графа
|
||||
Тезаурус по экологии:
|
||||
жизнедеятельность человека
|
||||
технологический процесс
|
||||
пространственный объем
|
||||
естественная экологическая система
|
||||
ценность природного объекта
|
||||
ценность природной среды
|
||||
субъект сохраняемой природной среды
|
||||
экологически значимый отход
|
||||
естественный состав природной среды
|
||||
искусственное изменение природной среды
|
||||
повреждение природного объекта
|
||||
восстановление природного объекта
|
||||
восстановление природной среды
|
||||
восстановимое изменение природной среды
|
||||
физически необратимое изменение природной среды
|
||||
источник воздействия хозяйственной деятельности
|
||||
благоприятный экологический эффект хозяйственной деятельности
|
||||
резерв ресурса целевой экологической зоны под декларации
|
||||
установленный запас ресурса целевой экологической зоны
|
||||
заявленное воздействие
|
||||
экологический аудит
|
||||
благоприятная природная среда жизнедеятельности
|
||||
благоприятная природная среда хозяйственной деятельности
|
||||
благоприятная экологическая зона
|
||||
виды экологической экспертизы
|
||||
государственное оперативное экологическое управление
|
||||
государственное экологическое управление
|
||||
границы применимости методики
|
||||
деклараций о выбросах, сбросах и физических воздействиях
|
||||
декларируемые воздействия
|
||||
декларируемые опосредованные воздействия
|
||||
документы методического обеспечения экологических отношений
|
||||
документы оценки воздействия
|
||||
документы экологического планирования
|
||||
Единый экологический реестр
|
||||
законодательство в области экологических отношений
|
||||
заключение экологического нормоконтроля
|
||||
зона экологического бедствия
|
||||
информационное обеспечение ЭО
|
||||
карта экологического зонирования
|
||||
муниципальное оперативное экологическое управление
|
||||
муниципальное экологическое управление
|
||||
муниципальный экологический контроль
|
||||
муниципальный экологический мониторинг
|
||||
научное обеспечение экологических отношений
|
||||
научный экологический совет
|
||||
неблагоприятная экологическая зона
|
||||
неопределенная экологическая зона
|
||||
неприемлемая экологическая зона
|
||||
общественное экологическое управление
|
||||
общественные экологические объединения
|
||||
общественный экологический контроль
|
||||
общественный экологический мониторинг
|
||||
объект оценки
|
||||
объект экологического нормоконтроля
|
||||
объект, подлежащий обязательному экологическому страхованию
|
||||
обязательное экологическое страхование
|
||||
опасная экологическая зона
|
||||
организации, осуществляющие научное обеспечение экологических отношений
|
||||
основания для ответственности в области экологических отношений
|
||||
приемлемая экологическая зона
|
||||
программа мероприятий по благоприятному изменению природной среды и снижению риска возникновения негативных экологических последствий
|
||||
производственное оперативное экологическое управление
|
||||
производственное экологическое управление
|
||||
производственный экологический контроль
|
||||
производственный экологический мониторинг
|
||||
прокурорский экологический надзор
|
||||
разрешение на воздействие на природную среду
|
||||
разрешение на выбросы, сбросы и физические воздействия
|
||||
разрешенные воздействия
|
||||
разрешенные опосредованные воздействия
|
||||
региональный экологический нормоконтроль
|
||||
региональное оперативное экологическое управление
|
||||
региональное экологическое нормирование
|
||||
региональное экологическое управление
|
||||
региональные экологические советы
|
||||
региональный экологический контроль
|
||||
региональный экологический мониторинг
|
||||
региональный экологический надзор
|
||||
способы возмещения экологического вреда
|
||||
стратегическая экологическая оценка
|
||||
субъект обязательного экологического страхования
|
||||
схема экологического зонирования
|
||||
технические и технологические экологические нормативы
|
||||
территория зонирования
|
||||
условия применимости норматива
|
||||
участники экологических отношений
|
||||
федеральный экологический нормоконтроль
|
||||
федеральное оперативное экологическое управление
|
||||
федеральное экологическое нормирование
|
||||
федеральное экологическое управление
|
||||
федеральный экологический контроль
|
||||
федеральный экологический мониторинг
|
||||
федеральный экологический надзор
|
||||
первичные нормативы благоприятной природной среды жизнедеятельности
|
||||
первичные нормативы благоприятной природной среды хозяйственной деятельности
|
||||
первичные нормативы опасной природной среды жизнедеятельности
|
||||
первичные нормативы приемлемой природной среды жизнедеятельности
|
||||
первичные нормативы сохраняемой природной среды
|
||||
целевая экологическая зона
|
||||
экологическая плата
|
||||
экологическая экспертиза
|
||||
экологический нормоконтроль
|
||||
экологические нормативы воздействия хозяйственной деятельности
|
||||
экологические нормативы последствий воздействия
|
||||
экологические нормативы природной среды
|
||||
экологическое зонирование по нормативам
|
||||
экологическое зонирование по целям
|
||||
экологическое нормирование
|
||||
экологическое управление
|
||||
экспертное экологическое заключение
|
||||
Муниципальный экологический план
|
||||
Ежегодный отчет о состоянии природной среды на территории Российской Федерации
|
||||
Ежегодный отчет о состоянии природной среды на территории муниципальных образований
|
||||
Порядок государственной аккредитации организаций, осуществляющих научное обеспечение экологических отношений
|
||||
Порядок государственной аккредитации экспертных организаций и экспертов в области экологических отношений
|
||||
Порядок научного обеспечения экологических отношений
|
||||
Положение о Научном экологическом совете
|
||||
Положение об экологическом нормоконтроле
|
||||
Положение об экологической экспертизе
|
||||
Методика расчета совокупного опосредованного воздействия на природную среду
|
||||
Положение об Едином экологическом реестре
|
||||
Методика оценки воздействия на природную среду
|
||||
Положение о мерах по благоприятному изменению природной среды и снижению риска возникновения негативных экологических последствий
|
||||
Перечень видов хозяйственной деятельности, для которых устанавливаются экологические нормативы природной среды хозяйственной деятельности
|
||||
Порядок утверждения экологических нормативов природной среды хозяйственной деятельности
|
||||
Порядок утверждения технических и технологических экологических нормативов
|
||||
Порядок утверждения экологических нормативов хозяйственной деятельности
|
||||
Методические рекомендации по разработке муниципальных экологических планов
|
||||
Методические рекомендации по разработке производственных экологических планов
|
||||
Федеральный экологический план
|
||||
Порядок разработки федеральных экологических планов
|
||||
Порядок проведения стратегической экологической оценки
|
||||
Методика расчета воздействия по опосредованному воздействию
|
||||
Порядок оформления разрешений на воздействие на природную среду
|
||||
Методика определения и изменения размера экологической платы
|
||||
Методика экологического мониторинга
|
||||
Методика оперативного экологического управления
|
||||
Методика экологического контроля
|
||||
Методика оценки экологического ущерба
|
||||
Правила экологического страхования
|
||||
Ежегодный отчет о состоянии природной среды на территории субъекта Российской Федерации
|
||||
Положение о Региональном экологическом совете субъекта Российской Федерации
|
||||
Порядок создания региональных экологических советов
|
||||
Порядок проведения публичных слушаний при рассмотрении проектов региональных схем экологического зонирования
|
||||
Региональный экологический план
|
||||
Порядок разработки региональных экологических планов
|
||||
Производственный экологический план
|
||||
жизнедеятельность
|
||||
технология
|
||||
хозяйственная деятельность
|
||||
производственная инфраструктура
|
||||
объект хозяйственной деятельности
|
||||
природный объект
|
||||
природная среда
|
||||
природная среда жизнедеятельности
|
||||
природная среда хозяйственной деятельности
|
||||
природный объект особого значения
|
||||
особо охраняемая природная территория
|
||||
сохраняемая природная среда
|
||||
действующий объект хозяйственной деятельности
|
||||
новый объект хозяйственной деятельности
|
||||
субъект хозяйственной деятельности
|
||||
работник субъекта хозяйственной деятельности
|
||||
отход
|
||||
выброс
|
||||
сброс
|
||||
размещение отходов
|
||||
размещенные отходы
|
||||
объект размещения отходов
|
||||
воздействие хозяйственной деятельности
|
||||
физическое воздействие
|
||||
мероприятие по благоприятному изменению природной среды
|
||||
технологически невосстановимое изменение природной среды
|
||||
опосредующая природная среда
|
||||
опосредующие свойства природной среды
|
||||
опосредованное воздействие
|
||||
территория опосредованного воздействия хозяйственной деятельности
|
||||
совокупное опосредованное воздействие на природную среду
|
||||
экологический эффект хозяйственной деятельности
|
||||
экологическое последствие
|
||||
экологическое правонарушение
|
||||
экологический вред
|
||||
экологический ущерб
|
||||
наилучшая доступная технология
|
||||
негативный экологический эффект хозяйственной деятельности
|
||||
негативное экологическое последствие хозяйственной деятельности
|
||||
реципиент воздействия
|
||||
мероприятие по снижению риска возникновения негативных экологических последствий
|
||||
мера по благоприятному изменению природной среды и снижению риска возникновения негативных экологических последствий
|
||||
экологическое отношение
|
||||
субъекты
|
||||
критерий незначительности воздействия
|
||||
незначительное воздействие хозяйственной деятельности
|
||||
критерий декларирования опосредованного воздействия
|
||||
первичный норматив
|
||||
экологический норматив
|
||||
баланс интересов
|
||||
экологическое зонирование
|
||||
экологических зон
|
||||
базовое состояние природной среды
|
||||
ресурс природной среды
|
||||
распределяемый ресурс природной ресурс
|
||||
квота опосредованного воздействия
|
||||
утраченный экологический ресурс
|
||||
критерий корректировки программ мероприятий
|
||||
экологическая экспертная оценка
|
||||
экологический экспертный расчет
|
||||
экологический нормоконтроль
|
||||
управленческое решение
|
||||
экологический мониторинг
|
||||
оперативное экологическое управление
|
||||
экологический контроль
|
||||
экологический надзор
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import pandas as pd\n",
|
||||
"\n",
|
||||
"import pymorphy2\n",
|
||||
"import cctext as ct\n",
|
||||
"\n",
|
||||
"from nltk.stem import SnowballStemmer\n",
|
||||
"stemmer = SnowballStemmer(language=\"russian\")\n",
|
||||
"# https://www.langust.ru/rus_gram/rus_gr06.shtml\n",
|
||||
"# stemmer.stem(\"обеспечение\")\n",
|
||||
"\n",
|
||||
"morpho = pymorphy2.MorphAnalyzer()\n",
|
||||
"parser = ct.RuParser()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"butyavka = morpho.parse('мюсли')\n",
|
||||
"butyavka[0].lexeme"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"ct.get_all_forms('танк')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# thesaurus = open('tests/data/thesaurus.txt', mode='r', encoding='UTF-8')\n",
|
||||
"thesaurus = open('tests/data/functions.txt', mode='r', encoding='UTF-8')\n",
|
||||
"content = [term.strip() for term in thesaurus.readlines()]\n",
|
||||
"thesaurus.close()\n",
|
||||
"\n",
|
||||
"inflect_datv = [ct.inflect(term, 'datv') for term in content]\n",
|
||||
"inflect_nomn1 = [ct.inflect(term, 'nomn') for term in inflect_datv]\n",
|
||||
"inflect_gent = [ct.inflect(term, 'gent') for term in content]\n",
|
||||
"inflect_nomn2 = [ct.inflect(term, 'nomn') for term in inflect_gent]\n",
|
||||
"\n",
|
||||
"data = zip(content, inflect_datv, inflect_nomn1, inflect_gent, inflect_nomn2)\n",
|
||||
"df = pd.DataFrame(data, columns =['Term', 'Datv', 'Inverse1', 'Gent', 'Inverse2'])\n",
|
||||
"df.to_excel('output.xlsx')"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "11938c6bc6919ae2720b4d5011047913343b08a43b18698fd82dedb0d4417594"
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3.9.5 64-bit",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.9.5"
|
||||
},
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "b8488343e509b415c98a857491a9b4c90395f9a45992da0bb6102fdf120e22ce"
|
||||
}
|
||||
},
|
||||
"orig_nbformat": 2
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,83 +0,0 @@
|
|||
''' Unit tests: conceptapi. '''
|
||||
import unittest
|
||||
|
||||
import cctext as cc
|
||||
|
||||
|
||||
class TestConceptAPI(unittest.TestCase):
|
||||
'''Test class for Concept API.'''
|
||||
def _assert_tags(self, actual: str, expected: str):
|
||||
self.assertEqual(set(cc.split_grams(actual)), set(cc.split_grams(expected)))
|
||||
|
||||
def test_parse(self):
|
||||
''' Test parsing. '''
|
||||
self._assert_tags(cc.parse(''), '')
|
||||
self._assert_tags(cc.parse('1'), 'NUMB,intg')
|
||||
self._assert_tags(cc.parse('слон', require_grams='masc'), 'NOUN,anim,masc,sing,nomn')
|
||||
|
||||
def test_normalize_word(self):
|
||||
''' Test normalize for single word. '''
|
||||
self.assertEqual(cc.normalize(''), '')
|
||||
self.assertEqual(cc.normalize('первого'), 'первый')
|
||||
self.assertEqual(cc.normalize('диких людей'), 'дикий человек')
|
||||
|
||||
def test_generate_lexeme(self):
|
||||
''' Test all lexical forms. '''
|
||||
self.assertEqual(cc.generate_lexeme(''), [])
|
||||
|
||||
forms = cc.generate_lexeme('наверное')
|
||||
self.assertEqual(len(forms), 1)
|
||||
self.assertEqual(forms[0][0], 'наверное')
|
||||
self._assert_tags(forms[0][1], 'CONJ,Prnt')
|
||||
|
||||
forms = cc.generate_lexeme('молодой человек')
|
||||
self.assertEqual(len(forms), 19)
|
||||
self.assertEqual(forms[0][0], 'молодой человек')
|
||||
self._assert_tags(forms[0][1], 'nomn,masc,sing,anim,NOUN')
|
||||
|
||||
def test_inflect(self):
|
||||
''' Test inflection. '''
|
||||
self.assertEqual(cc.inflect('', ''), '')
|
||||
self.assertEqual(cc.inflect('слона', 'nomn'), 'слон')
|
||||
self.assertEqual(cc.inflect('слона', 'ADJF'), 'слона')
|
||||
self.assertEqual(cc.inflect('слона', 'nomn,plur'), 'слоны')
|
||||
self.assertEqual(cc.inflect('слона', 'nomn, plur'), 'слоны')
|
||||
self.assertEqual(cc.inflect('шкала оценок', 'loct,plur'), 'шкалах оценок')
|
||||
|
||||
def test_find_substr(self):
|
||||
'''Test substring search'''
|
||||
self.assertEqual(cc.find_substr('', ''), (0, 0))
|
||||
self.assertEqual(cc.find_substr('сложного красивого слона', 'красивые слоном'), (9, 24))
|
||||
|
||||
def test_inflect_context(self):
|
||||
'''Test contex inflection'''
|
||||
self.assertEqual(cc.inflect_context('', '', ''), '')
|
||||
self.assertEqual(cc.inflect_context('красивый', '', 'чашка'), 'красивая')
|
||||
|
||||
def test_inflect_substitute(self):
|
||||
'''Test substitute inflection'''
|
||||
self.assertEqual(cc.inflect_substitute('', ''), '')
|
||||
self.assertEqual(cc.inflect_substitute('', 'слон'), '')
|
||||
self.assertEqual(cc.inflect_substitute('слон', ''), 'слон')
|
||||
self.assertEqual(cc.inflect_substitute('красивый бантик', 'кошкой'), 'красивым бантиком')
|
||||
|
||||
def test_inflect_dependant(self):
|
||||
''' Test coordination inflection. '''
|
||||
self.assertEqual(cc.inflect_dependant('', ''), '')
|
||||
self.assertEqual(cc.inflect_dependant('', 'слон'), '')
|
||||
self.assertEqual(cc.inflect_dependant('слон', ''), 'слон')
|
||||
self.assertEqual(cc.inflect_dependant('общий', 'мать'), 'общая')
|
||||
self.assertEqual(cc.inflect_dependant('синий', 'слонов'), 'синих')
|
||||
|
||||
def test_match_all_morpho(self):
|
||||
''' Test extracting matching morpho. '''
|
||||
self.assertEqual(cc.match_all_morpho('', ''), [])
|
||||
self.assertEqual(cc.match_all_morpho('горит город', ''), [])
|
||||
self.assertEqual(cc.match_all_morpho('горит город', 'NOUN'), [[6, 11]])
|
||||
self.assertEqual(cc.match_all_morpho('горит город', 'VERB'), [[0, 5]])
|
||||
self.assertEqual(cc.match_all_morpho('столица страны', 'NOUN'), [[0, 7], [8, 14]])
|
||||
self.assertEqual(cc.match_all_morpho('столица страны', 'NOUN,sing,nomn'), [[0, 7]])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
|
@ -1,32 +0,0 @@
|
|||
''' Unit tests: context. '''
|
||||
import unittest
|
||||
|
||||
from cctext.context import Entity, TermContext
|
||||
|
||||
class TestEntity(unittest.TestCase):
|
||||
'''Test Entity termform access.'''
|
||||
def setUp(self):
|
||||
self.alias = 'X1'
|
||||
self.nominal = 'человек'
|
||||
self.text1 = 'test1'
|
||||
self.form1 = ['sing','datv']
|
||||
self.entity = Entity(self.alias, self.nominal, [{'text': self.text1, 'grams': self.form1}])
|
||||
|
||||
def test_attributes(self):
|
||||
self.assertEqual(self.entity.alias, self.alias)
|
||||
self.assertEqual(self.entity.get_nominal(), self.nominal)
|
||||
self.assertEqual(self.entity.manual, [{'text': self.text1, 'grams': self.form1}])
|
||||
|
||||
def test_get_form(self):
|
||||
self.assertEqual(self.entity.get_form([]), self.nominal)
|
||||
self.assertEqual(self.entity.get_form(self.form1), self.text1)
|
||||
self.assertEqual(self.entity.get_form(['invalid tags']), '!Неизвестная граммема: invalid tags!')
|
||||
self.assertEqual(self.entity.get_form(['plur']), 'люди')
|
||||
|
||||
def test_set_nominal(self):
|
||||
new_nomial = 'TEST'
|
||||
self.assertEqual(self.entity.get_form(['plur']), 'люди')
|
||||
self.entity.set_nominal(new_nomial)
|
||||
self.assertEqual(self.entity.get_nominal(), new_nomial)
|
||||
self.assertEqual(self.entity.get_form(['plur']), new_nomial)
|
||||
self.assertEqual(self.entity.manual, [])
|
|
@ -1,44 +0,0 @@
|
|||
''' Unit tests: reference. '''
|
||||
import unittest
|
||||
|
||||
from cctext import EntityReference, ReferenceType, SyntacticReference, parse_reference
|
||||
|
||||
class TestReferences(unittest.TestCase):
|
||||
''' Test class for references. '''
|
||||
|
||||
def test_EntityReference(self):
|
||||
''' Testing EntityRefence basics. '''
|
||||
ref = EntityReference('X1', 'sing,nomn')
|
||||
self.assertEqual(ref.get_type(), ReferenceType.entity)
|
||||
self.assertEqual(ref.to_text(), '@{X1|sing,nomn}')
|
||||
|
||||
def test_SyntacticReference(self):
|
||||
''' Testing SyntacticReference basics. '''
|
||||
ref = SyntacticReference(-1, 'черный')
|
||||
self.assertEqual(ref.get_type(), ReferenceType.syntactic)
|
||||
self.assertEqual(ref.to_text(), '@{-1|черный}')
|
||||
|
||||
def test_parse_reference_invalid(self):
|
||||
''' Testing parsing reference invalid input. '''
|
||||
self.assertIsNone(parse_reference(''))
|
||||
self.assertIsNone(parse_reference('X1'))
|
||||
self.assertIsNone(parse_reference('invalid'))
|
||||
self.assertIsNone(parse_reference(' '))
|
||||
self.assertIsNone(parse_reference('@{|}'))
|
||||
self.assertIsNone(parse_reference('@{|черный}'))
|
||||
self.assertIsNone(parse_reference('@{ | }'))
|
||||
self.assertIsNone(parse_reference('@{-1| }'))
|
||||
self.assertIsNone(parse_reference('@{1| }'))
|
||||
self.assertIsNone(parse_reference('@{0|черный}'))
|
||||
|
||||
def test_parse_reference(self):
|
||||
''' Testing parsing reference text. '''
|
||||
ref = parse_reference('@{1| черный }')
|
||||
self.assertIsNotNone(ref)
|
||||
self.assertEqual(ref.to_text(), '@{1|черный}')
|
||||
self.assertEqual(ref.get_type(), ReferenceType.syntactic)
|
||||
|
||||
ref = parse_reference('@{X1 | VERB, past, sing}')
|
||||
self.assertIsNotNone(ref)
|
||||
self.assertEqual(ref.to_text(), '@{X1|VERB,past,sing}')
|
||||
self.assertEqual(ref.get_type(), ReferenceType.entity)
|
|
@ -1,107 +0,0 @@
|
|||
''' Unit tests: resolver. '''
|
||||
import unittest
|
||||
from typing import cast
|
||||
|
||||
from cctext import (
|
||||
EntityReference, TermContext, Entity, SyntacticReference,
|
||||
Resolver, ResolvedReference, Position, TermForm,
|
||||
resolve_entity, resolve_syntactic, extract_entities
|
||||
)
|
||||
|
||||
|
||||
class TestUtils(unittest.TestCase):
|
||||
''' Test utilitiy methods. '''
|
||||
def test_extract_entities(self):
|
||||
self.assertEqual(extract_entities(''), [])
|
||||
self.assertEqual(extract_entities('@{-1|черны}'), [])
|
||||
self.assertEqual(extract_entities('@{X1|nomn}'), ['X1'])
|
||||
self.assertEqual(extract_entities('@{X1|datv}'), ['X1'])
|
||||
self.assertEqual(extract_entities('@{X1|datv} @{X1|datv} @{X2|datv}'), ['X1', 'X2'])
|
||||
self.assertEqual(extract_entities('@{X1} | @{X1} | @{X2}'), [])
|
||||
|
||||
|
||||
class TestResolver(unittest.TestCase):
|
||||
'''Test reference Resolver.'''
|
||||
def setUp(self):
|
||||
self.context = cast(TermContext, {})
|
||||
self.context['X1'] = Entity('X1', 'человек')
|
||||
self.context['X2'] = Entity('X2', '')
|
||||
self.resolver = Resolver(self.context)
|
||||
|
||||
def test_resolve_entity(self):
|
||||
self.assertEqual(resolve_entity(EntityReference('X1', ''), self.context), 'человек')
|
||||
self.assertEqual(resolve_entity(EntityReference('X1', 'plur'), self.context), 'люди')
|
||||
self.assertEqual(resolve_entity(EntityReference('X2', ''), self.context), '!Отсутствует термин: X2!')
|
||||
self.assertEqual(resolve_entity(EntityReference('X1', 'invalid'), self.context), '!Неизвестная граммема: invalid!')
|
||||
self.assertEqual(resolve_entity(EntityReference('X123', 'plur'), self.context), '!Неизвестная сущность: X123!')
|
||||
|
||||
def test_resolve_syntactic(self):
|
||||
ref = ResolvedReference(ref=EntityReference('X1', 'sing,datv'), resolved='человеку')
|
||||
allrefs = [ref, ref, ref, ref]
|
||||
self.assertEqual(resolve_syntactic(SyntacticReference(text='умный', referral_offset=-1), 0, allrefs), '!Некорректное смещение: -1!')
|
||||
self.assertEqual(resolve_syntactic(SyntacticReference(text='умный', referral_offset=1), 3, allrefs), '!Некорректное смещение: 1!')
|
||||
self.assertEqual(resolve_syntactic(SyntacticReference(text='умный', referral_offset=1), 0, allrefs), 'умному')
|
||||
self.assertEqual(resolve_syntactic(SyntacticReference(text='умный', referral_offset=2), 0, allrefs), 'умному')
|
||||
self.assertEqual(resolve_syntactic(SyntacticReference(text='умный', referral_offset=3), 0, allrefs), 'умному')
|
||||
self.assertEqual(resolve_syntactic(SyntacticReference(text='умный', referral_offset=-1), 3, allrefs), 'умному')
|
||||
self.assertEqual(resolve_syntactic(SyntacticReference(text='умный', referral_offset=-2), 3, allrefs), 'умному')
|
||||
self.assertEqual(resolve_syntactic(SyntacticReference(text='умный', referral_offset=-3), 3, allrefs), 'умному')
|
||||
|
||||
def test_resolve_invalid(self):
|
||||
self.assertEqual(self.resolver.resolve(''), '')
|
||||
self.assertEqual(len(self.resolver.refs), 0)
|
||||
|
||||
self.assertEqual(self.resolver.resolve('simple text'), 'simple text')
|
||||
self.assertEqual(len(self.resolver.refs), 0)
|
||||
|
||||
self.assertEqual(self.resolver.resolve('simple @{unparsable ref} text'), 'simple @{unparsable ref} text')
|
||||
self.assertEqual(len(self.resolver.refs), 0)
|
||||
|
||||
def test_resolve_single(self):
|
||||
self.assertEqual(self.resolver.resolve('просто @{-1|умный} текст'), 'просто !Некорректное смещение: -1! текст')
|
||||
self.assertEqual(len(self.resolver.refs), 1)
|
||||
self.assertEqual(self.resolver.refs[0].pos_input, Position(7, 18))
|
||||
self.assertEqual(self.resolver.refs[0].pos_output, Position(7, 34))
|
||||
|
||||
self.assertEqual(self.resolver.resolve('просто @{X123|sing,nomn} текст'), 'просто !Неизвестная сущность: X123! текст')
|
||||
self.assertEqual(len(self.resolver.refs), 1)
|
||||
self.assertEqual(self.resolver.refs[0].pos_input, Position(7, 24))
|
||||
self.assertEqual(self.resolver.refs[0].pos_output, Position(7, 35))
|
||||
|
||||
self.assertEqual(self.resolver.resolve('@{X1|sing,nomn}'), 'человек')
|
||||
self.assertEqual(len(self.resolver.refs), 1)
|
||||
self.assertEqual(self.resolver.refs[0].pos_input, Position(0, 15))
|
||||
self.assertEqual(self.resolver.refs[0].pos_output, Position(0, 7))
|
||||
|
||||
self.assertEqual(self.resolver.resolve('просто @{X1|sing,nomn} текст'), 'просто человек текст')
|
||||
self.assertEqual(len(self.resolver.refs), 1)
|
||||
self.assertEqual(self.resolver.refs[0].pos_input, Position(7, 22))
|
||||
self.assertEqual(self.resolver.refs[0].pos_output, Position(7, 14))
|
||||
|
||||
def test_resolve_multiple(self):
|
||||
input = '@{X1|sing,datv} @{-1|умный} @{X1|plur} завидуют'
|
||||
self.assertEqual(self.resolver.resolve(input), 'человеку умному люди завидуют')
|
||||
self.assertEqual(len(self.resolver.refs), 3)
|
||||
self.assertEqual(self.resolver.refs[0].pos_input, Position(0, 15))
|
||||
self.assertEqual(self.resolver.refs[0].pos_output, Position(0, 8))
|
||||
self.assertEqual(self.resolver.refs[1].pos_input, Position(16, 27))
|
||||
self.assertEqual(self.resolver.refs[1].pos_output, Position(9, 15))
|
||||
self.assertEqual(self.resolver.refs[2].pos_input, Position(28, 38))
|
||||
self.assertEqual(self.resolver.refs[2].pos_output, Position(16, 20))
|
||||
|
||||
def test_resolve_manual_forms(self):
|
||||
self.context['X1'] = Entity(
|
||||
alias='X1',
|
||||
nominal='человек',
|
||||
manual_forms=[
|
||||
TermForm(text='тест1', grams='NOUN,sing'.split(',')),
|
||||
TermForm(text='тест2', grams='NOUN,datv,plur'.split(','))
|
||||
]
|
||||
)
|
||||
self.assertEqual(self.resolver.resolve('@{X1|NOUN,sing,nomn}'), 'тест1', 'Match subset')
|
||||
self.assertEqual(self.resolver.resolve('@{X1|NOUN,sing}'), 'тест1', 'Match full')
|
||||
self.assertEqual(self.resolver.resolve('@{X1|NOUN,datv,plur}'), 'тест2')
|
||||
self.assertEqual(self.resolver.resolve('@{X1|NOUN,plur,datv}'), 'тест2', 'Match any order')
|
||||
self.assertEqual(self.resolver.resolve('@{X1|datv,plur}'), 'тест2', 'Match missing POS')
|
||||
self.assertEqual(self.resolver.resolve('@{X1|NOUN,datv,sing}'), 'тест1')
|
||||
self.assertEqual(self.resolver.resolve('@{X1|VERB,datv,plur}'), 'человек')
|
|
@ -1,18 +0,0 @@
|
|||
''' Unit tests: rumodel. '''
|
||||
import unittest
|
||||
|
||||
from cctext import split_grams, combine_grams
|
||||
|
||||
|
||||
class TestTags(unittest.TestCase):
|
||||
'''Test tags manipulation.'''
|
||||
|
||||
def test_split_tags(self):
|
||||
self.assertEqual(split_grams(''), [])
|
||||
self.assertEqual(split_grams('NOUN'), ['NOUN'])
|
||||
self.assertEqual(split_grams('NOUN,plur,sing'), ['NOUN','plur','sing'])
|
||||
|
||||
def test_combine_tags(self):
|
||||
self.assertEqual(combine_grams([]), '')
|
||||
self.assertEqual(combine_grams(['NOUN']), 'NOUN')
|
||||
self.assertEqual(combine_grams(['NOUN','plur','sing']), 'NOUN,plur,sing')
|
|
@ -1,446 +0,0 @@
|
|||
''' Unit tests: ruparser. '''
|
||||
import unittest
|
||||
|
||||
from typing import Iterable, Optional
|
||||
from cctext import PhraseParser
|
||||
|
||||
parser = PhraseParser()
|
||||
|
||||
|
||||
class TestRuParser(unittest.TestCase):
|
||||
''' Test class for russian parsing. '''
|
||||
|
||||
def _assert_parse(self, text: str, expected: Iterable[str],
|
||||
require_index: int = -1,
|
||||
require_grams: Optional[Iterable[str]] = None):
|
||||
phrase = parser.parse(text, require_index, require_grams)
|
||||
self.assertIsNotNone(phrase)
|
||||
if phrase:
|
||||
self.assertEqual(phrase.get_morpho().tag.grammemes, set(expected))
|
||||
|
||||
def _assert_inflect(self, text: str, tags: list[str], expected: str):
|
||||
model = parser.parse(text)
|
||||
if not model:
|
||||
result = text
|
||||
else:
|
||||
result = model.inflect(frozenset(tags))
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_parse_word(self):
|
||||
''' Test parse for single word. '''
|
||||
self._assert_parse('1', ['NUMB', 'intg'])
|
||||
self._assert_parse('пять', ['NUMR', 'nomn'])
|
||||
self._assert_parse('трёх', ['NUMR', 'gent'])
|
||||
self._assert_parse('трех', ['NUMR', 'gent'])
|
||||
self._assert_parse('круча', ['NOUN', 'femn', 'sing', 'nomn', 'inan'])
|
||||
self._assert_parse('круть', ['NOUN', 'femn', 'sing', 'nomn', 'inan', 'Sgtm', 'Geox'])
|
||||
self._assert_parse('ПВО', ['NOUN', 'femn', 'sing', 'nomn', 'inan', 'Sgtm', 'Abbr', 'Fixd'])
|
||||
self._assert_parse('СМИ', ['NOUN', 'plur', 'nomn', 'inan', 'Pltm', 'Abbr', 'Fixd', 'GNdr'])
|
||||
self._assert_parse('ему', ['NPRO', 'masc', 'sing', 'datv', '3per', 'Anph'])
|
||||
self._assert_parse('крутит', ['VERB', 'sing', '3per', 'pres', 'impf', 'tran', 'indc'])
|
||||
self._assert_parse('смеркалось', ['VERB', 'neut', 'sing', 'Impe', 'past', 'impf', 'intr', 'indc'])
|
||||
self._assert_parse('крутить', ['INFN', 'impf', 'tran'])
|
||||
self._assert_parse('крученый', ['ADJF', 'masc', 'sing', 'nomn'])
|
||||
self._assert_parse('крут', ['ADJS', 'masc', 'sing', 'Qual'])
|
||||
self._assert_parse('крутящего', ['PRTF', 'masc', 'sing', 'gent', 'pres', 'impf', 'tran', 'actv'])
|
||||
self._assert_parse('откручен', ['PRTS', 'masc', 'sing', 'past', 'perf', 'pssv'])
|
||||
self._assert_parse('крутя', ['GRND', 'pres', 'impf', 'tran'])
|
||||
self._assert_parse('круто', ['ADVB'])
|
||||
self._assert_parse('круче', ['COMP', 'Qual'])
|
||||
self._assert_parse(',', ['PNCT'])
|
||||
self._assert_parse('32-', ['intg', 'NUMB'])
|
||||
|
||||
self._assert_parse('слон', ['NOUN', 'anim', 'masc', 'sing', 'nomn'], require_index=0)
|
||||
self._assert_parse('слон', ['NOUN', 'anim', 'masc', 'sing', 'nomn'], require_grams=['masc'])
|
||||
self._assert_parse('прямой', ['ADJF', 'gent', 'sing', 'femn', 'Qual'], require_index=0)
|
||||
self._assert_parse('прямой', ['ADJF', 'datv', 'Qual', 'sing', 'femn'], require_index=1)
|
||||
self._assert_parse('прямой', ['NOUN', 'sing', 'inan', 'femn', 'gent'], require_grams=['NOUN'])
|
||||
|
||||
self._assert_parse('консистенции', ['NOUN', 'inan', 'femn', 'plur', 'nomn'])
|
||||
self._assert_parse('тест', ['NOUN', 'sing', 'masc', 'inan', 'nomn'])
|
||||
self._assert_parse('петля', ['NOUN', 'inan', 'femn', 'sing', 'nomn'])
|
||||
|
||||
self._assert_parse('Слон', ['NOUN', 'anim', 'masc', 'sing', 'nomn'])
|
||||
self._assert_parse('СМИ', ['NOUN', 'Pltm', 'GNdr', 'Fixd', 'inan', 'Abbr', 'plur', 'nomn'])
|
||||
self.assertEqual(parser.parse('КАиП'), None)
|
||||
self.assertEqual(parser.parse('СЛОН'), None)
|
||||
self.assertEqual(parser.parse(''), None)
|
||||
self.assertEqual(parser.parse('слон', require_grams=set(['femn'])), None)
|
||||
self.assertEqual(parser.parse('32', require_grams=set(['NOUN'])), None)
|
||||
self.assertEqual(parser.parse('32-', require_grams=set(['NOUN'])), None)
|
||||
self.assertEqual(parser.parse('слон', require_index=42), None)
|
||||
|
||||
def test_parse_text(self):
|
||||
''' Test parse for multiword sequences. '''
|
||||
self._assert_parse(', ,', ['PNCT'])
|
||||
self._assert_parse('слон,', ['NOUN', 'anim', 'masc', 'sing', 'nomn'])
|
||||
|
||||
self._assert_parse('синий слон', ['NOUN', 'anim', 'masc', 'sing', 'nomn'])
|
||||
self._assert_parse('слон синий', ['NOUN', 'anim', 'masc', 'sing', 'nomn'])
|
||||
self._assert_parse('тихий Дон', ['NOUN', 'anim', 'masc', 'sing', 'nomn'])
|
||||
self._assert_parse('слон, лежащий на траве', ['NOUN', 'anim', 'masc', 'sing', 'nomn'])
|
||||
self._assert_parse('лежащий на траве слон', ['NOUN', 'anim', 'masc', 'sing', 'nomn'])
|
||||
self._assert_parse('города улиц', ['NOUN', 'nomn', 'plur', 'masc', 'inan'])
|
||||
self._assert_parse('первый дом улиц города', ['NOUN', 'inan', 'masc', 'nomn', 'sing'])
|
||||
self._assert_parse('быстро едет', ['VERB', 'intr', 'impf', '3per', 'sing', 'indc', 'pres'])
|
||||
self._assert_parse('летучий 1-2-пептид', ['NOUN', 'masc', 'nomn', 'sing', 'inan'])
|
||||
|
||||
self._assert_parse('прямой угол', ['NOUN', 'masc', 'nomn', 'inan', 'sing'])
|
||||
self._assert_parse('прямого угла', ['NOUN', 'sing', 'inan', 'masc', 'gent'])
|
||||
self._assert_parse('угла прямой', ['NOUN', 'sing', 'inan', 'masc', 'gent'])
|
||||
self._assert_parse('бесконечной прямой', ['NOUN', 'gent', 'femn', 'sing', 'inan'])
|
||||
self._assert_parse('складские операции', ['NOUN', 'femn', 'plur', 'inan', 'nomn'])
|
||||
self._assert_parse('незначительному воздействию хозяйственной деятельности',
|
||||
['NOUN', 'datv', 'sing', 'neut', 'inan'])
|
||||
|
||||
self._assert_parse('варить овсянку', ['INFN', 'tran', 'impf'])
|
||||
self._assert_parse('варить рис', ['INFN', 'tran', 'impf'])
|
||||
|
||||
self._assert_parse('нарочито сложный', ['ADJF', 'sing', 'masc', 'nomn', 'Qual'])
|
||||
self._assert_parse('части программы', ['NOUN', 'femn', 'plur', 'nomn', 'inan'])
|
||||
self._assert_parse('летучий 1-2-фторметил', ['NOUN', 'nomn', 'sing', 'masc', 'inan'])
|
||||
self._assert_parse('отрезок времени', ['NOUN', 'nomn', 'sing', 'masc', 'inan'])
|
||||
self._assert_parse('портки сушить', ['INFN', 'impf', 'tran'])
|
||||
self._assert_parse('портки вешай', ['VERB', 'tran', 'impr', 'impf', 'sing', 'excl'])
|
||||
self._assert_parse('Анализирует состояние организации.',
|
||||
['VERB', 'sing', 'tran', 'pres', '3per', 'impf', 'indc'])
|
||||
self._assert_parse('Во взаимодействии с подразделениями Генеральной прокуратуры формирует перечень показателей',
|
||||
['VERB', 'sing', 'tran', 'pres', '3per', 'impf', 'indc'])
|
||||
|
||||
def test_parse_coordination(self):
|
||||
''' Test parse coordination info. '''
|
||||
self.assertEqual(parser.parse('говорить').coordination, [-1, 1])
|
||||
self.assertEqual(parser.parse('ворчливая карга').coordination, [2, -1, 0])
|
||||
self.assertEqual(parser.parse('страна, объятая пожаром').coordination, [-1, -1, 2, -1, 2])
|
||||
self.assertEqual(parser.parse('тихо говорил').coordination, [-1, -1, 2])
|
||||
|
||||
def test_normalize_word(self):
|
||||
''' Test normalize for single word. '''
|
||||
self.assertEqual(parser.normalize(''), '')
|
||||
self.assertEqual(parser.normalize('123'), '123')
|
||||
self.assertEqual(parser.normalize('test'), 'test')
|
||||
self.assertEqual(parser.normalize('первого'), 'первый')
|
||||
self.assertEqual(parser.normalize('слону'), 'слон')
|
||||
self.assertEqual(parser.normalize('слонам'), 'слон')
|
||||
self.assertEqual(parser.normalize('обеспечил'), 'обеспечить')
|
||||
self.assertEqual(parser.normalize('сильную'), 'сильный')
|
||||
self.assertEqual(parser.normalize('бежавший'), 'бежать')
|
||||
self.assertEqual(parser.normalize('1 2 3'), '1 2 3')
|
||||
|
||||
def test_normalize_text(self):
|
||||
''' Test normalize for multiword collation. '''
|
||||
self.assertEqual(parser.normalize('синего слона'), 'синий слон')
|
||||
self.assertEqual(parser.normalize('тихо говоривший'), 'тихо говорить')
|
||||
self.assertEqual(parser.normalize('канавой квартала'), 'канава квартала')
|
||||
|
||||
def test_inflect_word(self):
|
||||
''' Test inflection for single word. '''
|
||||
self._assert_inflect('', [], '')
|
||||
self._assert_inflect('invalid', [], 'invalid')
|
||||
self._assert_inflect('invalid', ['nomn'], 'invalid')
|
||||
self._assert_inflect('', ['nomn'], '')
|
||||
self._assert_inflect('123', ['nomn'], '123')
|
||||
self._assert_inflect('слона', [], 'слона')
|
||||
self._assert_inflect('слона', ['ADJF'], 'слона')
|
||||
|
||||
self._assert_inflect('слона', ['nomn'], 'слон')
|
||||
self._assert_inflect('объектоид', ['datv'], 'объектоиду')
|
||||
self._assert_inflect('терм-функция', ['datv'], 'терм-функции')
|
||||
|
||||
self._assert_inflect('Слона', ['nomn'], 'Слон')
|
||||
self._assert_inflect('СМИ', ['datv'], 'СМИ')
|
||||
self._assert_inflect('КАНС', ['datv'], 'КАНС')
|
||||
self._assert_inflect('КАиП', ['datv'], 'КАиП')
|
||||
self._assert_inflect('АТ', ['datv'], 'АТ')
|
||||
self._assert_inflect('А-проекция', ['datv'], 'А-проекции')
|
||||
|
||||
def test_inflect_noun(self):
|
||||
''' Test inflection for single noun. '''
|
||||
self._assert_inflect('книга', ['nomn'], 'книга')
|
||||
self._assert_inflect('книга', ['gent'], 'книги')
|
||||
self._assert_inflect('книга', ['datv'], 'книге')
|
||||
self._assert_inflect('книга', ['accs'], 'книгу')
|
||||
self._assert_inflect('книга', ['ablt'], 'книгой')
|
||||
self._assert_inflect('книга', ['loct'], 'книге')
|
||||
self._assert_inflect('люди', ['loct'], 'людях')
|
||||
|
||||
self._assert_inflect('книга', ['plur'], 'книги')
|
||||
self._assert_inflect('люди', ['sing'], 'человек')
|
||||
self._assert_inflect('человек', ['plur'], 'люди')
|
||||
self._assert_inflect('человек', ['plur', 'loct'], 'людях')
|
||||
|
||||
self._assert_inflect('человеку', ['masc'], 'человеку')
|
||||
self._assert_inflect('человеку', ['neut'], 'человеку')
|
||||
self._assert_inflect('человека', ['femn'], 'человека')
|
||||
self._assert_inflect('человека', ['past'], 'человека')
|
||||
|
||||
def test_inflect_npro(self):
|
||||
''' Test inflection for single pronoun. '''
|
||||
self._assert_inflect('меня', ['nomn'], 'я')
|
||||
self._assert_inflect('я', ['gent'], 'меня')
|
||||
self._assert_inflect('я', ['datv'], 'мне')
|
||||
self._assert_inflect('я', ['accs'], 'меня')
|
||||
self._assert_inflect('я', ['ablt'], 'мной')
|
||||
self._assert_inflect('я', ['loct'], 'мне')
|
||||
|
||||
self._assert_inflect('я', ['ADJF'], 'я')
|
||||
self._assert_inflect('я', ['NOUN'], 'я')
|
||||
self._assert_inflect('я', ['2per'], 'я')
|
||||
self._assert_inflect('я', ['past'], 'я')
|
||||
|
||||
def test_inflect_numr(self):
|
||||
''' Test inflection for single numeric. '''
|
||||
self._assert_inflect('трёх', ['nomn'], 'три')
|
||||
self._assert_inflect('три', ['gent'], 'трёх')
|
||||
self._assert_inflect('три', ['datv'], 'трём')
|
||||
self._assert_inflect('три', ['accs', 'inan'], 'три')
|
||||
self._assert_inflect('три', ['accs', 'anim'], 'трёх')
|
||||
self._assert_inflect('три', ['ablt'], 'тремя')
|
||||
self._assert_inflect('три', ['loct'], 'трёх')
|
||||
|
||||
def test_inflect_adjf(self):
|
||||
''' Test inflection for single adjectif. '''
|
||||
self._assert_inflect('хороший', ['nomn'], 'хороший')
|
||||
self._assert_inflect('хороший', ['gent'], 'хорошего')
|
||||
self._assert_inflect('хороший', ['datv'], 'хорошему')
|
||||
self._assert_inflect('хороший', ['accs'], 'хорошего')
|
||||
self._assert_inflect('хороший', ['ablt'], 'хорошим')
|
||||
self._assert_inflect('хороший', ['loct'], 'хорошем')
|
||||
|
||||
self._assert_inflect('хороший', ['plur'], 'хорошие')
|
||||
self._assert_inflect('хорошие', ['sing'], 'хороший')
|
||||
self._assert_inflect('хорошие', ['sing', 'datv'], 'хорошему')
|
||||
self._assert_inflect('хорошие', ['plur', 'masc', 'datv'], 'хорошим')
|
||||
|
||||
self._assert_inflect('хорошая', ['masc'], 'хороший')
|
||||
self._assert_inflect('перепончатокрылое', ['masc'], 'перепончатокрылый')
|
||||
self._assert_inflect('хороший', ['neut'], 'хорошее')
|
||||
self._assert_inflect('хорошая', ['neut'], 'хорошее')
|
||||
self._assert_inflect('хороший', ['femn'], 'хорошая')
|
||||
self._assert_inflect('перепончатокрылое', ['femn'], 'перепончатокрылая')
|
||||
|
||||
self._assert_inflect('хороший', ['masc', 'femn'], 'хороший')
|
||||
self._assert_inflect('хороший', ['plur', 'femn'], 'хорошие')
|
||||
self._assert_inflect('хороший', ['past'], 'хороший')
|
||||
|
||||
def test_inflect_prtf(self):
|
||||
''' Test inflection for single participle. '''
|
||||
self._assert_inflect('бегущего', ['nomn'], 'бегущий')
|
||||
self._assert_inflect('бегущий', ['gent'], 'бегущего')
|
||||
self._assert_inflect('бегущий', ['datv'], 'бегущему')
|
||||
self._assert_inflect('бегущий', ['accs'], 'бегущего')
|
||||
self._assert_inflect('бегущий', ['ablt'], 'бегущим')
|
||||
self._assert_inflect('бегущий', ['loct'], 'бегущем')
|
||||
self._assert_inflect('бегущая', ['loct'], 'бегущей')
|
||||
self._assert_inflect('бежавшая', ['loct'], 'бежавшей')
|
||||
|
||||
self._assert_inflect('бегущий', ['plur'], 'бегущие')
|
||||
self._assert_inflect('бегущие', ['sing'], 'бегущий')
|
||||
self._assert_inflect('бегущие', ['sing', 'datv'], 'бегущему')
|
||||
|
||||
self._assert_inflect('бегущий', ['femn'], 'бегущая')
|
||||
self._assert_inflect('бегущий', ['neut'], 'бегущее')
|
||||
self._assert_inflect('бегущая', ['masc'], 'бегущий')
|
||||
|
||||
self._assert_inflect('бегущий', ['past'], 'бежавший')
|
||||
self._assert_inflect('бежавших', ['pres'], 'бегущих')
|
||||
|
||||
self._assert_inflect('бегущий', ['masc', 'femn'], 'бегущий')
|
||||
self._assert_inflect('бегущий', ['plur', 'femn'], 'бегущие')
|
||||
|
||||
def test_inflect_verb(self):
|
||||
''' Test inflection for single verb. '''
|
||||
self._assert_inflect('говорить', ['1per'], 'говорю')
|
||||
self._assert_inflect('говорить', ['2per'], 'говоришь')
|
||||
self._assert_inflect('говорить', ['2per', 'plur'], 'говорите')
|
||||
self._assert_inflect('говорить', ['3per'], 'говорит')
|
||||
|
||||
self._assert_inflect('говорите', ['1per'], 'говорим')
|
||||
self._assert_inflect('говорите', ['3per'], 'говорят')
|
||||
|
||||
self._assert_inflect('говорит', ['plur'], 'говорят')
|
||||
self._assert_inflect('говорят', ['sing'], 'говорит')
|
||||
|
||||
self._assert_inflect('говорит', ['past'], 'говорил')
|
||||
self._assert_inflect('говорил', ['pres'], 'говорю')
|
||||
|
||||
self._assert_inflect('говорили', ['sing'], 'говорил')
|
||||
self._assert_inflect('говорил', ['plur'], 'говорили')
|
||||
|
||||
self._assert_inflect('говорила', ['masc'], 'говорил')
|
||||
self._assert_inflect('говорили', ['masc'], 'говорил')
|
||||
self._assert_inflect('говорил', ['neut'], 'говорило')
|
||||
self._assert_inflect('говорил', ['femn'], 'говорила')
|
||||
|
||||
self._assert_inflect('говорить', ['datv'], 'говорить')
|
||||
|
||||
def test_inflect_text_nominal(self):
|
||||
''' Test inflection for multiword text in nominal form. '''
|
||||
self._assert_inflect('синий короткий', ['accs', 'sing', 'femn'], 'синюю короткую')
|
||||
self._assert_inflect('красивые слоны', ['accs', 'sing'], 'красивого слона')
|
||||
self._assert_inflect('вход процесса', ['loct', 'plur'], 'входах процесса')
|
||||
self._assert_inflect('нарочито сложный тест', ['datv', 'sing'], 'нарочито сложному тесту')
|
||||
self._assert_inflect('первый дом улиц города', ['loct', 'plur'], 'первых домах улиц города')
|
||||
self._assert_inflect('шкала оценок', ['loct', 'plur'], 'шкалах оценок')
|
||||
self._assert_inflect('складские операции', ['sing', 'datv'], 'складской операции')
|
||||
self._assert_inflect('стороны конфликтного перехода', ['loct', 'sing'], 'стороне конфликтного перехода')
|
||||
self._assert_inflect('уникомплексные тектологические переходы', ['loct', 'sing'],
|
||||
'уникомплексном тектологическом переходе')
|
||||
|
||||
self._assert_inflect('слабый НИР', ['datv', 'sing'], 'слабому НИР')
|
||||
self._assert_inflect('слабый НИР', ['accs', 'plur'], 'слабых НИР')
|
||||
self._assert_inflect('летучий 1-2-бутан', ['ablt', 'sing'], 'летучим 1-2-бутаном')
|
||||
self._assert_inflect('летучий 1-2-фторметил', ['ablt', 'sing'], 'летучим 1-2-фторметилом')
|
||||
|
||||
self._assert_inflect('красивые процессы', ['accs', 'sing'], 'красивого процесс')
|
||||
self._assert_inflect('красивые процессы', ['gent', 'sing'], 'красивого процесса')
|
||||
self._assert_inflect('части программы', ['ablt', 'sing'], 'части программой')
|
||||
self._assert_inflect('первые здания', ['ablt', 'sing'], 'первым зданием')
|
||||
self._assert_inflect('прямой слон', ['ablt', 'sing'], 'прямым слоном')
|
||||
|
||||
self._assert_inflect('тихо говорить', ['past', 'masc'], 'тихо говорил')
|
||||
self._assert_inflect('быть готовым', ['past', 'masc'], 'был готовым')
|
||||
self._assert_inflect('уметь готовить', ['pres', '2per'], 'умеешь готовить')
|
||||
self._assert_inflect('готовить рис', ['pres', '1per'], 'готовлю рис')
|
||||
|
||||
# self._assert_inflect('десять миллионов', ['datv'], 'десяти миллионам')
|
||||
# self._assert_inflect('десять апельсинов', ['datv'], 'десяти апельсинов')
|
||||
# self._assert_inflect('два миллиона', ['datv'], 'двум миллионам')
|
||||
|
||||
self._assert_inflect('техногенема n-го порядка', ['datv'], 'техногенеме n-го порядка')
|
||||
self._assert_inflect('Положение об органе АБВ', ['datv'], 'Положению об органе АБВ')
|
||||
|
||||
def test_inflect_text_cross(self):
|
||||
''' Test inflection for multiword text in multiple forms. '''
|
||||
self._assert_inflect('слона кота', ['nomn'], 'слон кота')
|
||||
self._assert_inflect('готовкой риса', ['nomn'], 'готовка риса')
|
||||
|
||||
# self._assert_inflect('реципиенту воздействия', ['nomn'], 'реципиент воздействия')
|
||||
|
||||
def test_inflect_complex_mainword(self):
|
||||
''' Test inflection of mainword conmprised of multiple words. '''
|
||||
# Do not parse complex main words
|
||||
self._assert_inflect('слона и кота', ['nomn'], 'слон и кота')
|
||||
self._assert_inflect('сказал и поехал', ['INFN'], 'сказать и поехал')
|
||||
|
||||
def test_inflect_word_pos(self):
|
||||
''' Test inflection for word changing pars of speech. '''
|
||||
self._assert_inflect('обеспечит', ['INFN'], 'обеспечить')
|
||||
self._assert_inflect('обеспечить', ['VERB', '1per'], 'обеспечу')
|
||||
# self._assert_inflect('обеспечить', ['NOUN', 'sing','nomn'], 'обеспечение')
|
||||
# self._assert_inflect('обеспечить', ['NOUN', 'plur','datv'], 'обеспечениям')
|
||||
# self._assert_inflect('синеть', ['NOUN'], 'синь')
|
||||
# self._assert_inflect('готовить', ['NOUN', 'sing'], 'готовка')
|
||||
# self._assert_inflect('обеспечить', ['ADJF'], '???')
|
||||
# self._assert_inflect('обеспечить', ['ADJS'], '???')
|
||||
# self._assert_inflect('синеть', ['ADJF'], 'синий')
|
||||
# self._assert_inflect('готовить', ['ADJF', 'sing', 'femn'], 'готовая')
|
||||
self._assert_inflect('обеспечить', ['PRTF', 'plur', 'past'], 'обеспечившие')
|
||||
self._assert_inflect('обеспечить', ['PRTS', 'plur'], 'обеспечены')
|
||||
self._assert_inflect('обеспечить', ['GRND', 'past'], 'обеспечив')
|
||||
# self._assert_inflect('обеспечить', ['ADVB'], 'обеспечённо')
|
||||
# self._assert_inflect('обеспечить', ['COMP'], 'обеспеченнее')
|
||||
|
||||
# self._assert_inflect('обеспечение', ['INFN'], 'обеспечить')
|
||||
# self._assert_inflect('обеспечение', ['VERB','1per'], 'обеспечу')
|
||||
self._assert_inflect('обеспечение', ['NOUN', 'plur', 'nomn'], 'обеспечения')
|
||||
self._assert_inflect('обеспечение', ['NOUN', 'plur', 'datv'], 'обеспечениям')
|
||||
# self._assert_inflect('синь', ['ADJF'], 'синий')
|
||||
# self._assert_inflect('обеспечение', ['PRTF', 'plur', 'past'], 'обеспечившие')
|
||||
# self._assert_inflect('обеспечение', ['PRTS', 'plur'], 'обеспечены')
|
||||
# self._assert_inflect('обеспечение', ['GRND', 'past'], 'обеспечив')
|
||||
# self._assert_inflect('обеспечение', ['ADVB'], 'обеспечённо')
|
||||
# self._assert_inflect('обеспечение', ['COMP'], 'обеспеченнее')
|
||||
|
||||
# self._assert_inflect('синий', ['INFN'], 'синеть')
|
||||
# self._assert_inflect('синий', ['VERB','1per'], 'синею')
|
||||
# self._assert_inflect('синий', ['NOUN', 'plur','nomn'], 'синьки')
|
||||
# self._assert_inflect('синий', ['NOUN', 'plur','datv'], 'синькам')
|
||||
self._assert_inflect('синий', ['ADJS'], 'синь')
|
||||
self._assert_inflect('хороший', ['ADJS'], 'хорош')
|
||||
# self._assert_inflect('синий', ['PRTF', 'plur', 'past'], 'синевшие')
|
||||
# self._assert_inflect('синий', ['PRTS', 'plur'], '??')
|
||||
# self._assert_inflect('синий', ['GRND', 'past'], 'синев')
|
||||
# self._assert_inflect('хороший', ['ADVB'], 'хорошо')
|
||||
self._assert_inflect('синий', ['COMP'], 'синее')
|
||||
|
||||
self._assert_inflect('обеспечащий', ['INFN'], 'обеспечить')
|
||||
self._assert_inflect('обеспечивающий', ['INFN'], 'обеспечивать')
|
||||
self._assert_inflect('бегущий', ['INFN'], 'бежать')
|
||||
self._assert_inflect('бегущий', ['VERB'], 'бегу')
|
||||
self._assert_inflect('бежавшего', ['VERB'], 'бежал')
|
||||
# self._assert_inflect('обеспечащий', ['NOUN', 'plur','datv'], 'обеспечениям')
|
||||
# self._assert_inflect('синеющий', ['NOUN'], 'синь')
|
||||
# self._assert_inflect('готовящий', ['NOUN', 'sing'], 'готовка')
|
||||
# self._assert_inflect('синеющий', ['ADJF'], 'синий')
|
||||
self._assert_inflect('обеспечащий', ['PRTF', 'plur', 'past'], 'обеспечившие')
|
||||
self._assert_inflect('обеспечащий', ['PRTS', 'plur'], 'обеспечимы')
|
||||
self._assert_inflect('обеспечащий', ['GRND', 'past'], 'обеспечив')
|
||||
# self._assert_inflect('обеспечащий', ['ADVB'], 'обеспечённо')
|
||||
# self._assert_inflect('обеспечащий', ['COMP'], 'обеспеченнее')
|
||||
|
||||
def test_inflect_text_pos(self):
|
||||
''' Test inflection for multiword text changing parts of speech. '''
|
||||
# self._assert_inflect('готовить еду', ['NOUN', 'sing'], 'готовка еды')
|
||||
# self._assert_inflect('обеспечение безопасности', ['INFN'], 'обеспечить безопасность')
|
||||
# self._assert_inflect('сильный удар по мячу', ['INFN'], 'сильно ударить по мячу')
|
||||
self._assert_inflect('сильно обиженный', ['INFN'], 'сильно обидеть')
|
||||
# self._assert_inflect('сильно обиженный', ['NOUN'], 'сильная обида')
|
||||
# self._assert_inflect('надежно обеспечить', ['NOUN'], 'надежное обеспечение')
|
||||
|
||||
def test_inflect_invalid_text(self):
|
||||
''' Test inflection for multiword not coordinated text. '''
|
||||
self._assert_inflect('синими слоны', ['nomn', 'sing'], 'синими слон')
|
||||
|
||||
def test_inflect_context(self):
|
||||
''' Test content inflection. '''
|
||||
self.assertEqual(parser.inflect_context('', '', ''), '')
|
||||
self.assertEqual(parser.inflect_context('', 'красивый', ''), '')
|
||||
self.assertEqual(parser.inflect_context('', '', 'в'), '')
|
||||
self.assertEqual(parser.inflect_context('слон', '', ''), 'слон')
|
||||
|
||||
self.assertEqual(parser.inflect_context('красивый', '', 'чашка'), 'красивая')
|
||||
self.assertEqual(parser.inflect_context('красивый', '', 'черного'), 'красивого')
|
||||
self.assertEqual(parser.inflect_context('слон', '', 'черного'), 'слона')
|
||||
self.assertEqual(parser.inflect_context('слоны', 'сильный', 'черную'), 'слон')
|
||||
self.assertEqual(parser.inflect_context('город', 'огня', ''), 'города')
|
||||
# self.assertEqual(parser.inflect_context('улица', 'дом', ''), 'улицы')
|
||||
|
||||
self.assertEqual(parser.inflect_context('большой город', 'стильного', 'необъятной страны'), 'большого города')
|
||||
self.assertEqual(parser.inflect_context('город', '', ', расположенного неподалеку'), 'города')
|
||||
|
||||
def test_inflect_substitute(self):
|
||||
''' Test substitute inflection. '''
|
||||
self.assertEqual(parser.inflect_substitute('', ''), '')
|
||||
self.assertEqual(parser.inflect_substitute('123', '123'), '123')
|
||||
self.assertEqual(parser.inflect_substitute('', 'слон'), '')
|
||||
self.assertEqual(parser.inflect_substitute('слон', ''), 'слон')
|
||||
self.assertEqual(parser.inflect_substitute('слон', 'слон'), 'слон')
|
||||
self.assertEqual(parser.inflect_substitute('слон', 'слоны'), 'слоны')
|
||||
self.assertEqual(parser.inflect_substitute('слон', 'кошкой'), 'слоном')
|
||||
self.assertEqual(parser.inflect_substitute('синий слон', 'стильного чайника'), 'синего слона')
|
||||
self.assertEqual(parser.inflect_substitute('варить клюкву', 'осуществляет'), 'варит клюкву')
|
||||
|
||||
def test_inflect_dependant(self):
|
||||
''' Test coordination inflection. '''
|
||||
self.assertEqual(parser.inflect_dependant('', ''), '')
|
||||
self.assertEqual(parser.inflect_dependant('', 'слон'), '')
|
||||
self.assertEqual(parser.inflect_dependant('слон', ''), 'слон')
|
||||
self.assertEqual(parser.inflect_dependant('общий', 'мать'), 'общая')
|
||||
self.assertEqual(parser.inflect_dependant('синий', 'слонов'), 'синих')
|
||||
self.assertEqual(parser.inflect_dependant('белый длинный', 'столами'), 'белыми длинными')
|
||||
|
||||
def test_find_substr(self):
|
||||
''' Test substring search. '''
|
||||
self.assertEqual(parser.find_substr('', ''), (0, 0))
|
||||
self.assertEqual(parser.find_substr('слон', ''), (0, 0))
|
||||
self.assertEqual(parser.find_substr('', 'слон'), (0, 0))
|
||||
self.assertEqual(parser.find_substr('слон', 'слон'), (0, 4))
|
||||
self.assertEqual(parser.find_substr('сложного слона', 'слон'), (9, 14))
|
||||
self.assertEqual(parser.find_substr('сложного слона', 'слоном'), (9, 14))
|
||||
self.assertEqual(parser.find_substr('сложного красивого слона', 'красивые слоном'), (9, 24))
|
||||
self.assertEqual(parser.find_substr('человек', 'люди'), (0, 7))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
|
@ -1,62 +0,0 @@
|
|||
''' Unit tests: syntax. '''
|
||||
import unittest
|
||||
|
||||
from cctext import RuSyntax, Capitalization
|
||||
|
||||
|
||||
class TestRusSyntax(unittest.TestCase):
|
||||
''' Test class for russian syntax. '''
|
||||
|
||||
def test_capitalization(self):
|
||||
''' Testing capitalization. '''
|
||||
self.assertEqual(Capitalization.from_text(''), Capitalization.unknwn)
|
||||
self.assertEqual(Capitalization.from_text('Альфа'), Capitalization.first_capital)
|
||||
self.assertEqual(Capitalization.from_text('АЛЬФА'), Capitalization.upper_case)
|
||||
self.assertEqual(Capitalization.from_text('альфа'), Capitalization.lower_case)
|
||||
self.assertEqual(Capitalization.from_text('альФа'), Capitalization.mixed)
|
||||
self.assertEqual(Capitalization.from_text('альфА'), Capitalization.mixed)
|
||||
self.assertEqual(Capitalization.from_text('КАиП'), Capitalization.mixed)
|
||||
|
||||
self.assertEqual(Capitalization.upper_case.apply_to('альфа'), 'АЛЬФА')
|
||||
self.assertEqual(Capitalization.lower_case.apply_to('АльФа'), 'альфа')
|
||||
self.assertEqual(Capitalization.first_capital.apply_to('альфа'), 'Альфа')
|
||||
self.assertEqual(Capitalization.first_capital.apply_to('АльФа'), 'АльФа')
|
||||
self.assertEqual(Capitalization.unknwn.apply_to('АльФа'), 'АльФа')
|
||||
self.assertEqual(Capitalization.mixed.apply_to('АльФа'), 'АльФа')
|
||||
|
||||
def test_is_single_word(self):
|
||||
''' Testing single word identification. '''
|
||||
self.assertTrue(RuSyntax.is_single_word(''))
|
||||
self.assertTrue(RuSyntax.is_single_word('word'))
|
||||
self.assertTrue(RuSyntax.is_single_word('слово'))
|
||||
self.assertTrue(RuSyntax.is_single_word(' word '), 'Whitespace doesnt count')
|
||||
self.assertTrue(RuSyntax.is_single_word('1001'), 'Numbers are words')
|
||||
self.assertTrue(RuSyntax.is_single_word('кое-как'), 'Hyphen doesnt break work')
|
||||
self.assertTrue(RuSyntax.is_single_word('1-2-метилбутан'), 'Complex words')
|
||||
self.assertFalse(RuSyntax.is_single_word('one two'))
|
||||
self.assertFalse(RuSyntax.is_single_word('синий слон'))
|
||||
|
||||
def test_tokenize(self):
|
||||
''' Testing tokenization. '''
|
||||
self.assertEqual(list(RuSyntax.tokenize('')), [])
|
||||
self.assertEqual(list(RuSyntax.tokenize(' ')), [])
|
||||
self.assertEqual(self._list_tokenize('test'), [(0, 4, 'test')])
|
||||
self.assertEqual(self._list_tokenize(' test '), [(1, 5, 'test')])
|
||||
self.assertEqual(self._list_tokenize('синий слон'), [(0, 5, 'синий'), (6, 10, 'слон')])
|
||||
|
||||
def test_split_words(self):
|
||||
''' Testing splitting text into words. '''
|
||||
self.assertEqual([], list(RuSyntax.split_words('')))
|
||||
self.assertEqual([], list(RuSyntax.split_words(' ')))
|
||||
self.assertEqual(RuSyntax.split_words('test'), ['test'])
|
||||
self.assertEqual(RuSyntax.split_words(' test '), ['test'])
|
||||
self.assertEqual(RuSyntax.split_words('синий слон'), ['синий', 'слон'])
|
||||
self.assertEqual(RuSyntax.split_words('синий, большой слон'), ['синий', ',', 'большой', 'слон'])
|
||||
|
||||
@staticmethod
|
||||
def _list_tokenize(text: str):
|
||||
return [(token.start, token.stop, token.text) for token in RuSyntax.tokenize(text)]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
|
@ -1,13 +1,12 @@
|
|||
tzdata==2024.1
|
||||
Django==5.0.3
|
||||
Django==5.0.4
|
||||
djangorestframework==3.15.1
|
||||
django-cors-headers==4.3.1
|
||||
django-filter==24.2
|
||||
drf-spectacular==0.27.1
|
||||
drf-spectacular==0.27.2
|
||||
coreapi==2.3.3
|
||||
pymorphy3==2.0.1
|
||||
razdel==0.5.0
|
||||
django-rest-passwordreset==1.4.0
|
||||
cctext==0.1.1
|
||||
|
||||
psycopg2-binary==2.9.9
|
||||
gunicorn==21.2.0
|
|
@ -5,8 +5,7 @@ django-cors-headers
|
|||
django-filter
|
||||
drf-spectacular
|
||||
coreapi
|
||||
pymorphy3
|
||||
razdel
|
||||
cctext
|
||||
|
||||
mypy
|
||||
pylint
|
||||
|
|
79
rsconcept/frontend/package-lock.json
generated
79
rsconcept/frontend/package-lock.json
generated
|
@ -35,8 +35,8 @@
|
|||
"@lezer/generator": "^1.7.0",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/node": "^20.12.7",
|
||||
"@types/react": "^18.2.75",
|
||||
"@types/react-dom": "^18.2.24",
|
||||
"@types/react": "^18.2.77",
|
||||
"@types/react-dom": "^18.2.25",
|
||||
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
||||
"@typescript-eslint/parser": "^6.21.0",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
|
@ -50,7 +50,7 @@
|
|||
"postcss": "^8.4.38",
|
||||
"tailwindcss": "^3.4.3",
|
||||
"ts-jest": "^29.1.2",
|
||||
"typescript": "^5.4.4",
|
||||
"typescript": "^5.4.5",
|
||||
"vite": "^4.5.3"
|
||||
}
|
||||
},
|
||||
|
@ -614,9 +614,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@codemirror/autocomplete": {
|
||||
"version": "6.15.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.15.0.tgz",
|
||||
"integrity": "sha512-G2Zm0mXznxz97JhaaOdoEG2cVupn4JjPaS4AcNvZzhOsnnG9YVN68VzfoUw6dYTsIxT6a/cmoFEN47KAWhXaOg==",
|
||||
"version": "6.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.16.0.tgz",
|
||||
"integrity": "sha512-P/LeCTtZHRTCU4xQsa89vSKWecYv1ZqwzOd5topheGRf+qtacFgBeIMQi3eL8Kt/BUNvxUWkx+5qP2jlGoARrg==",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
|
@ -691,9 +691,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@codemirror/view": {
|
||||
"version": "6.26.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.26.2.tgz",
|
||||
"integrity": "sha512-j6V48PlFC/O7ERAR5vRW5QKDdchzmyyfojDdt+zPsB0YXoWgcjlC1IWjmlYfx08aQZ3HN5BtALcgGgtSKGMe7A==",
|
||||
"version": "6.26.3",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.26.3.tgz",
|
||||
"integrity": "sha512-gmqxkPALZjkgSxIeeweY/wGQXBfwTUaLs8h7OKtSwfbj9Ct3L11lD+u1sS7XHppxFQoMDiMDp07P9f3I2jWOHw==",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.4.0",
|
||||
"style-mod": "^4.1.0",
|
||||
|
@ -2828,18 +2828,18 @@
|
|||
"integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q=="
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "18.2.75",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.75.tgz",
|
||||
"integrity": "sha512-+DNnF7yc5y0bHkBTiLKqXFe+L4B3nvOphiMY3tuA5X10esmjqk7smyBZzbGTy2vsiy/Bnzj8yFIBL8xhRacoOg==",
|
||||
"version": "18.2.77",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.77.tgz",
|
||||
"integrity": "sha512-CUT9KUUF+HytDM7WiXKLF9qUSg4tGImwy4FXTlfEDPEkkNUzJ7rVFolYweJ9fS1ljoIaP7M7Rdjc5eUm/Yu5AA==",
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-dom": {
|
||||
"version": "18.2.24",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.24.tgz",
|
||||
"integrity": "sha512-cN6upcKd8zkGy4HU9F1+/s98Hrp6D4MOcippK4PoE8OZRngohHZpbJn1GsaDLz87MqvHNoT13nHvNqM9ocRHZg==",
|
||||
"version": "18.2.25",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.25.tgz",
|
||||
"integrity": "sha512-o/V48vf4MQh7juIKZU2QGDfli6p1+OOi5oXx36Hffpc9adsHeXjVp8rHuPkjd8VT8sOJ2Zp05HR7CdpGTIUFUA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/react": "*"
|
||||
|
@ -3779,9 +3779,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001608",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001608.tgz",
|
||||
"integrity": "sha512-cjUJTQkk9fQlJR2s4HMuPMvTiRggl0rAVMtthQuyOlDWuqHXqN8azLq+pi8B2TjwKJ32diHjUqRIKeFX4z1FoA==",
|
||||
"version": "1.0.30001609",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001609.tgz",
|
||||
"integrity": "sha512-JFPQs34lHKx1B5t1EpQpWH4c+29zIyn/haGsbpfq3suuV9v56enjFt23zqijxGTMwy1p/4H2tjnQMY+p1WoAyA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
|
@ -4369,9 +4369,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/dedent": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz",
|
||||
"integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==",
|
||||
"version": "1.5.3",
|
||||
"resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz",
|
||||
"integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"babel-plugin-macros": "^3.1.0"
|
||||
|
@ -4511,9 +4511,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.4.731",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.731.tgz",
|
||||
"integrity": "sha512-+TqVfZjpRz2V/5SPpmJxq9qK620SC5SqCnxQIOi7i/U08ZDcTpKbT7Xjj9FU5CbXTMUb4fywbIr8C7cGv4hcjw=="
|
||||
"version": "1.4.735",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.735.tgz",
|
||||
"integrity": "sha512-pkYpvwg8VyOTQAeBqZ7jsmpCjko1Qc6We1ZtZCjRyYbT5v4AIUKDy5cQTRotQlSSZmMr8jqpEt6JtOj5k7lR7A=="
|
||||
},
|
||||
"node_modules/ellipsize": {
|
||||
"version": "0.5.1",
|
||||
|
@ -5929,15 +5929,22 @@
|
|||
}
|
||||
},
|
||||
"node_modules/its-fine": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/its-fine/-/its-fine-1.2.0.tgz",
|
||||
"integrity": "sha512-518vLgHK/dgGxyZj4MdLrDRryziqR1M+JbVtjw1tmdgvZQYsJvB2Leoe2qFOHPalZ5KiAOK18wTmIC0XszYc0w==",
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/its-fine/-/its-fine-1.2.5.tgz",
|
||||
"integrity": "sha512-fXtDA0X0t0eBYAGLVM5YsgJGsJ5jEmqZEPrGbzdf5awjv0xE7nqv3TVnvtUF060Tkes15DbDAKW/I48vsb6SyA==",
|
||||
"dependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-reconciler": "*"
|
||||
"@types/react-reconciler": "^0.28.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8"
|
||||
"react": ">=18.0"
|
||||
}
|
||||
},
|
||||
"node_modules/its-fine/node_modules/@types/react-reconciler": {
|
||||
"version": "0.28.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.28.8.tgz",
|
||||
"integrity": "sha512-SN9c4kxXZonFhbX4hJrZy37yw9e7EIxcpHCxQv5JUS18wDE5ovkQKlqQEkufdJCCMfuI9BnjUJvhYeJ9x5Ra7g==",
|
||||
"dependencies": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/jackspeak": {
|
||||
|
@ -9816,9 +9823,9 @@
|
|||
"integrity": "sha512-Uzz8C/5GesJzv8i+Y2prEMYUwodwZySPcNhuJUdsVMH2Yn4Nm8qlbQe6qRN5fOhg55XB0WiLfTPBxVHxpE60ug=="
|
||||
},
|
||||
"node_modules/three-mesh-bvh": {
|
||||
"version": "0.7.3",
|
||||
"resolved": "https://registry.npmjs.org/three-mesh-bvh/-/three-mesh-bvh-0.7.3.tgz",
|
||||
"integrity": "sha512-3W6KjzmupjfE89GuHPT31kxKWZ4YGZPEZJNysJpiOZfQRsBQQgmK7v/VJPpjG6syhAvTnY+5Fr77EvIkTLpGSw==",
|
||||
"version": "0.7.4",
|
||||
"resolved": "https://registry.npmjs.org/three-mesh-bvh/-/three-mesh-bvh-0.7.4.tgz",
|
||||
"integrity": "sha512-flxe0A4uflTPR6elgq/Y8VrLoljDNS899i422SxQcU3EtMj6o8z4kZRyqZqGWzR0qMf1InTZzY1/0xZl/rnvVw==",
|
||||
"peerDependencies": {
|
||||
"three": ">= 0.151.0"
|
||||
}
|
||||
|
@ -10016,9 +10023,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.4.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.4.tgz",
|
||||
"integrity": "sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==",
|
||||
"version": "5.4.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
|
||||
"integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
|
|
|
@ -39,8 +39,8 @@
|
|||
"@lezer/generator": "^1.7.0",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/node": "^20.12.7",
|
||||
"@types/react": "^18.2.75",
|
||||
"@types/react-dom": "^18.2.24",
|
||||
"@types/react": "^18.2.77",
|
||||
"@types/react-dom": "^18.2.25",
|
||||
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
||||
"@typescript-eslint/parser": "^6.21.0",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
|
@ -54,7 +54,7 @@
|
|||
"postcss": "^8.4.38",
|
||||
"tailwindcss": "^3.4.3",
|
||||
"ts-jest": "^29.1.2",
|
||||
"typescript": "^5.4.4",
|
||||
"typescript": "^5.4.5",
|
||||
"vite": "^4.5.3"
|
||||
},
|
||||
"jest": {
|
||||
|
|
|
@ -11,8 +11,8 @@ function BackendLint() {
|
|||
|
||||
Set-Location $backend
|
||||
$env:DJANGO_SETTINGS_MODULE = "project.settings"
|
||||
& $pylint cctext project apps
|
||||
& $mypy cctext project apps
|
||||
& $pylint project apps
|
||||
& $mypy project apps
|
||||
}
|
||||
|
||||
RunLinters
|
Loading…
Reference in New Issue
Block a user