Changeset a90371d in rtems-central


Ignore:
Timestamp:
May 8, 2020, 3:09:34 PM (5 months ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
master
Children:
e2429ea
Parents:
1767cc8
git-author:
Sebastian Huber <sebastian.huber@…> (05/08/20 15:09:34)
git-committer:
Sebastian Huber <sebastian.huber@…> (05/28/20 08:38:22)
Message:

content: Add enabled_by_to_exp()

Location:
rtemsqual
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • rtemsqual/content.py

    r1767cc8 ra90371d  
    529529        yield
    530530        self.add(["#ifdef __cplusplus", "}", "#endif"])
     531
     532
     533class ExpressionMapper:
     534    """ Maps symbols and operations to form a C expression. """
     535
     536    # pylint: disable=no-self-use
     537    def map(self, symbol: str) -> str:
     538        """ Maps a symbol to build an expression. """
     539        return f"defined({symbol})"
     540
     541    def op_and(self) -> str:
     542        """ Returns the and operator. """
     543        return " && "
     544
     545    def op_or(self) -> str:
     546        """ Returns the or operator. """
     547        return " || "
     548
     549    def op_not(self, symbol: str) -> str:
     550        """ Returns the negation of the symbol. """
     551        return f"!{symbol}"
     552
     553
     554class PythonExpressionMapper(ExpressionMapper):
     555    """ Maps symbols and operations to form a Python expression. """
     556
     557    # pylint: disable=no-self-use
     558    def map(self, symbol: str) -> str:
     559        return symbol
     560
     561    def op_and(self) -> str:
     562        return " and "
     563
     564    def op_or(self) -> str:
     565        return " or "
     566
     567    def op_not(self, symbol: str) -> str:
     568        return f"not {symbol}"
     569
     570
     571def _to_expression_op(enabled_by: Any, mapper: ExpressionMapper,
     572                      operation: str) -> str:
     573    symbols = [
     574        _to_expression(next_enabled_by, mapper)
     575        for next_enabled_by in enabled_by
     576    ]
     577    if len(symbols) == 1:
     578        return symbols[0]
     579    return f"({operation.join(symbols)})"
     580
     581
     582def _to_expression_op_and(enabled_by: Any, mapper: ExpressionMapper) -> str:
     583    return _to_expression_op(enabled_by, mapper, mapper.op_and())
     584
     585
     586def _to_expression_op_not(enabled_by: Any, mapper: ExpressionMapper) -> str:
     587    return mapper.op_not(_to_expression(enabled_by, mapper))
     588
     589
     590def _to_expression_op_or(enabled_by: Any, mapper: ExpressionMapper) -> str:
     591    return _to_expression_op(enabled_by, mapper, mapper.op_or())
     592
     593
     594_TO_EXPRESSION_OP = {
     595    "and": _to_expression_op_and,
     596    "not": _to_expression_op_not,
     597    "or": _to_expression_op_or
     598}
     599
     600
     601def _to_expression(enabled_by: Any, mapper: ExpressionMapper) -> str:
     602    if isinstance(enabled_by, list):
     603        return _to_expression_op_or(enabled_by, mapper)
     604    if isinstance(enabled_by, dict):
     605        if len(enabled_by) == 1:
     606            key = next(iter(enabled_by))
     607            return _TO_EXPRESSION_OP[key](enabled_by[key], mapper)
     608        raise ValueError
     609    return mapper.map(enabled_by)
     610
     611
     612def enabled_by_to_exp(enabled_by: Any, mapper: ExpressionMapper) -> str:
     613    """
     614    Returns an expression for an enabled-by attribute value.
     615    """
     616    exp = _to_expression(enabled_by, mapper)
     617    if exp.startswith("("):
     618        return exp[1:-1]
     619    return exp
  • rtemsqual/tests/test_content.py

    r1767cc8 ra90371d  
    2626
    2727import os
     28import pytest
    2829
    29 from rtemsqual.content import Content
     30from rtemsqual.content import Content, enabled_by_to_exp, \
     31    ExpressionMapper, PythonExpressionMapper
    3032
    3133
     
    116118        assert src.read() == """x
    117119"""
     120
     121
     122def to_c_exp(enabled_by):
     123    return enabled_by_to_exp(enabled_by, ExpressionMapper())
     124
     125
     126def test_enabled_by_to_exp():
     127    assert to_c_exp([]) == ""
     128    assert to_c_exp(["A"]) == "defined(A)"
     129    assert to_c_exp(["B"]) == "defined(B)"
     130    assert to_c_exp(["A", "B"]) == "defined(A) || defined(B)"
     131    assert to_c_exp({"not": "A"}) == "!defined(A)"
     132    assert to_c_exp({"and": ["A", "B"]}) == "defined(A) && defined(B)"
     133    assert to_c_exp({"and": ["A", "B", {
     134        "not": "C"
     135    }]}) == "defined(A) && defined(B) && !defined(C)"
     136    assert to_c_exp(
     137        {
     138            "not": {
     139                "and":
     140                ["A",
     141                 {
     142                     "not": ["B", "C",
     143                             {
     144                                 "and": ["D",
     145                                         {
     146                                             "not": "E"
     147                                         }]
     148                             }]
     149                 }]
     150            }
     151        }
     152    ) == "!(defined(A) && !(defined(B) || defined(C) || (defined(D) && !defined(E))))"
     153    with pytest.raises(KeyError):
     154        to_c_exp({"foo": "bar"})
     155    with pytest.raises(ValueError):
     156        to_c_exp({"foo": "bar", "bla": "blub"})
     157
     158
     159def to_python_exp(enabled_by):
     160    return enabled_by_to_exp(enabled_by, PythonExpressionMapper())
     161
     162
     163def test_enabled_by_to_python_exp():
     164    assert to_python_exp([]) == ""
     165    assert to_python_exp(["A"]) == "A"
     166    assert to_python_exp(["B"]) == "B"
     167    assert to_python_exp(["A", "B"]) == "A or B"
     168    assert to_python_exp({"not": "A"}) == "not A"
     169    assert to_python_exp({"and": ["A", "B"]}) == "A and B"
     170    assert to_python_exp({"and": ["A", "B", {
     171        "not": "C"
     172    }]}) == "A and B and not C"
     173    assert to_python_exp({
     174        "not": {
     175            "and": ["A", {
     176                "not": ["B", "C", {
     177                    "and": ["D", {
     178                        "not": "E"
     179                    }]
     180                }]
     181            }]
     182        }
     183    }) == "not (A and not (B or C or (D and not E)))"
     184    with pytest.raises(KeyError):
     185        to_python_exp({"foo": "bar"})
     186    with pytest.raises(ValueError):
     187        to_python_exp({"foo": "bar", "bla": "blub"})
  • rtemsqual/tests/test_content_c.py

    r1767cc8 ra90371d  
    2424# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    2525# POSSIBILITY OF SUCH DAMAGE.
     26
     27import pytest
    2628
    2729from rtemsqual.content import CContent
Note: See TracChangeset for help on using the changeset viewer.