File: introspector.py

package info (click to toggle)
python-rebulk 3.3.0-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 752 kB
  • sloc: python: 7,497; makefile: 3
file content (124 lines) | stat: -rw-r--r-- 3,857 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Introspect rebulk object to retrieve capabilities.
"""
from abc import ABCMeta, abstractmethod
from collections import defaultdict

from .pattern import StringPattern, RePattern, FunctionalPattern
from .utils import extend_safe


class Description(metaclass=ABCMeta):
    """
    Abstract class for a description.
    """
    @property
    @abstractmethod
    def properties(self):  # pragma: no cover
        """
        Properties of described object.
        :return: all properties that described object can generate grouped by name.
        :rtype: dict
        """


class PatternDescription(Description):
    """
    Description of a pattern.
    """
    def __init__(self, pattern):  # pylint:disable=too-many-branches
        self.pattern = pattern
        self._properties = defaultdict(list)

        if pattern.properties:
            for key, values in pattern.properties.items():
                extend_safe(self._properties[key], values)
        elif 'value' in pattern.match_options:
            self._properties[pattern.name].append(pattern.match_options['value'])
        elif isinstance(pattern, StringPattern):
            extend_safe(self._properties[pattern.name], pattern.patterns)
        elif isinstance(pattern, RePattern):
            if pattern.name and pattern.name not in pattern.private_names:
                extend_safe(self._properties[pattern.name], [None])
            if not pattern.private_children:
                for regex_pattern in pattern.patterns:
                    for group_name, values in regex_pattern.groupindex.items():
                        if group_name not in pattern.private_names:
                            extend_safe(self._properties[group_name], [None])
        elif isinstance(pattern, FunctionalPattern):
            if pattern.name and pattern.name not in pattern.private_names:
                extend_safe(self._properties[pattern.name], [None])


    @property
    def properties(self):
        """
        Properties for this rule.
        :return:
        :rtype: dict
        """
        return self._properties


class RuleDescription(Description):
    """
    Description of a rule.
    """
    def __init__(self, rule):
        self.rule = rule

        self._properties = defaultdict(list)

        if rule.properties:
            for key, values in rule.properties.items():
                extend_safe(self._properties[key], values)

    @property
    def properties(self):
        """
        Properties for this rule.
        :return:
        :rtype: dict
        """
        return self._properties


class Introspection(Description):
    """
    Introspection results.
    """
    def __init__(self, rebulk, context=None):
        self.patterns = [PatternDescription(pattern) for pattern in rebulk.effective_patterns(context)
                         if not pattern.private and not pattern.marker]
        self.rules = [RuleDescription(rule) for rule in rebulk.effective_rules(context)]

    @property
    def properties(self):
        """
        Properties for Introspection results.
        :return:
        :rtype:
        """
        properties = defaultdict(list)
        for pattern in self.patterns:
            for key, values in pattern.properties.items():
                extend_safe(properties[key], values)
        for rule in self.rules:
            for key, values in rule.properties.items():
                extend_safe(properties[key], values)
        return properties


def introspect(rebulk, context=None):
    """
    Introspect a Rebulk instance to grab defined objects and properties that can be generated.
    :param rebulk:
    :type rebulk: Rebulk
    :param context:
    :type context:
    :return: Introspection instance
    :rtype: Introspection
    """
    return Introspection(rebulk, context)