Esempio n. 1
0
def callback_active_jumper(pin: Pin) -> None:
    value: bool = True if pin.value() else False

    if config.active() == value:
        return

    config.active(value)
Esempio n. 2
0
def build_library(cfg, rules):
    lib = {"on_file": [], "on_line": [], "on_token": []}

    for kind in rules:
        for rule in rules[kind]:
            inst = rule()
            if inst.mandatory or config.active(cfg, inst.name):
                lib[kind].append(inst)

    return lib
Esempio n. 3
0
def callback_light_sensor(pin: Pin) -> None:

    new_value: int = not pin.value()
    if config.LIGHT_SENSOR_STATE == new_value:
        return

    config.LIGHT_SENSOR_STATE = new_value
    print("Light-Sensor: " + str(new_value))

    # check if even active
    if not config.active():
        return

    # If there's no more light, execute all this shiet
    if not config.LIGHT_SENSOR_STATE:
        exec_camera_shutter()
Esempio n. 4
0
from machine import Pin, SoftI2C
from sh1106 import SH1106, SH1106_I2C

from menu import MainMenu

from time import sleep
from time import time

import config

#
# Create Display
#
i2c: SoftI2C = SoftI2C(scl=Pin(22), sda=Pin(21), freq=400000)
config.DISPLAY = SH1106_I2C(128, 64, i2c, addr=0x3c)
config.DISPLAY.sleep(False)

#
# Create Menu
#
config.MAIN_MENU = MainMenu(config.DISPLAY)

# Updates values on main menu
config.delay(config.delay())
config.blob(config.blob())
config.active(config.active())

# Impoprt pin listeners
import pinListener
Esempio n. 5
0
def stage_3_analysis(mh, cfg, tbuf, is_embedded):
    assert isinstance(mh, Message_Handler)
    assert isinstance(tbuf, Token_Buffer)
    assert isinstance(is_embedded, bool)

    in_copyright_notice = (config.active(cfg, "copyright_notice")
                           and (not is_embedded
                                or cfg["copyright_in_embedded_code"]))
    company_copyright_found = False
    generic_copyright_found = False
    copyright_token = None
    copyright_notice = []

    # Some state needed to fix indentation
    statement_start_token = None
    current_indent = 0
    enclosing_ast = None

    for n, token in enumerate(tbuf.tokens):
        if n - 1 >= 0:
            prev_token = tbuf.tokens[n - 1]
        else:
            prev_token = None

        if n + 1 < len(tbuf.tokens):
            next_token = tbuf.tokens[n + 1]
        else:
            next_token = None

        if (prev_token and prev_token.location.line == token.location.line):
            prev_in_line = prev_token
            ws_before = (token.location.col_start -
                         prev_in_line.location.col_end) - 1

        else:
            prev_in_line = None
            ws_before = None

        if (next_token and next_token.location.line == token.location.line):
            if next_token.kind == "NEWLINE":
                next_in_line = None
                ws_after = None
            else:
                next_in_line = next_token
                ws_after = (next_in_line.location.col_start -
                            token.location.col_end) - 1
        else:
            next_in_line = None
            ws_after = None

        # Keep track of statement starters. This is required for
        # indentation.
        if token.first_in_statement:
            # We need to take special care of comments that are the
            # first thing after an open block. Since comments are not
            # attached to the AST (and it is not practical to do so),
            # most of the time we can just indent them to "same as
            # above". But if they are the first item inside e.g. an if
            # statement, then this won't work (the previous
            # indentation level is one too low).
            if statement_start_token and \
               statement_start_token.kind == "KEYWORD" and \
               statement_start_token.value == "end":
                # The previous token was 'end'. We don't need to
                # do anything in this case, since we'll re-use the
                # indentation level of the compound statement
                enclosing_ast = None
            elif statement_start_token and \
                 statement_start_token.ast_link and \
                 statement_start_token.ast_link.causes_indentation():
                # We've got a previous AST node. We remember it,
                # and indent one level below it, but only if it is
                # a statement that would create nesting.
                enclosing_ast = statement_start_token.ast_link

            statement_start_token = token

        # Recognize justifications
        if token.kind in ("COMMENT", "CONTINUATION"):
            if "mh:ignore_style" in token.value:
                mh.register_justification(token)

        # Don't ever check anonymous tokens
        if token.anonymous:
            continue

        # Corresponds to the old CodeChecker CopyrightCheck rule
        if in_copyright_notice:
            if token.kind == "COMMENT":
                match = re.search(COPYRIGHT_REGEX, token.value)
                if match:
                    # We have a sane copyright string
                    copyright_token = token
                    generic_copyright_found = True
                    if match.group("org").strip() in cfg["copyright_entity"]:
                        company_copyright_found = True

                elif copyright_token is None:
                    # We might find something that could look like a
                    # copyright, but is not quite right
                    for org in cfg["copyright_entity"]:
                        if org.lower() in token.value.lower():
                            copyright_token = token
                            break
                    for substr in ("(c)", "copyright"):
                        if substr in token.value.lower():
                            copyright_token = token
                            break

                copyright_notice.append(token.value)

            else:
                # Once we get a non-comment token, the header has
                # ended. We then emit messages if we could not find
                # anything.
                in_copyright_notice = False

                if len(copyright_notice) == 0:
                    mh.style_issue(
                        token.location, "file does not appear to contain any"
                        " copyright header")
                elif company_copyright_found:
                    # Everything is fine
                    pass
                elif generic_copyright_found:
                    # If we have something basic, we only raise an
                    # issue if we're supposed to have something
                    # specific.
                    if cfg["copyright_entity"]:
                        mh.style_issue(
                            copyright_token.location,
                            "Copyright does not mention one of %s" %
                            (" or ".join(cfg["copyright_entity"])))
                elif copyright_token:
                    # We found something that might be a copyright,
                    # but is not in a sane format
                    mh.style_issue(copyright_token.location,
                                   "Copyright notice not in right format")
                else:
                    # We found nothing
                    mh.style_issue(token.location,
                                   "No copyright notice found in header")

        # Corresponds to the old CodeChecker CommaWhitespace
        # rule. CommaLineEndings is now folded into the new
        # end_of_statements rule, which is much more strict and
        # complete.
        if token.kind == "COMMA":
            if config.active(cfg, "whitespace_comma"):
                token.fix.ensure_trim_before = True
                token.fix.ensure_ws_after = True

                if (next_in_line and ws_after == 0) or \
                   (prev_in_line and ws_before > 0):
                    mh.style_issue(
                        token.location,
                        "comma cannot be preceeded by whitespace "
                        "and must be followed by whitespace", True)

        elif token.kind == "COLON":
            if config.active(cfg, "whitespace_colon"):
                if prev_in_line and prev_in_line.kind == "COMMA":
                    pass
                    # We don't deal with this here. If anything it's the
                    # problem of the comma whitespace rules.
                elif next_in_line and \
                     next_in_line.kind == "CONTINUATION":
                    # Special exception in the rare cases we
                    # continue a range expression
                    if prev_in_line and ws_before > 0:
                        token.fix.ensure_trim_before = True
                        mh.style_issue(token.location,
                                       "no whitespace before colon", True)
                elif (prev_in_line and ws_before > 0) or \
                     (next_in_line and ws_after > 0):
                    token.fix.ensure_trim_before = True
                    token.fix.ensure_trim_after = True
                    mh.style_issue(token.location, "no whitespace around colon"
                                   " allowed", True)

        # Corresponds to the old CodeChecker EqualSignWhitespace rule
        elif token.kind == "ASSIGNMENT":
            if config.active(cfg, "whitespace_assignment"):
                token.fix.ensure_ws_before = True
                token.fix.ensure_ws_after = True

                if prev_in_line and ws_before == 0:
                    mh.style_issue(token.location,
                                   "= must be preceeded by whitespace", True)
                elif next_in_line and ws_after == 0:
                    mh.style_issue(token.location,
                                   "= must be succeeded by whitespace", True)

        # Corresponds to the old CodeChecker ParenthesisWhitespace and
        # BracketsWhitespace rules
        elif token.kind in ("BRA", "A_BRA", "M_BRA"):
            if config.active(cfg, "whitespace_brackets") and \
               next_in_line and ws_after > 0 and \
               next_in_line.kind != "CONTINUATION":
                mh.style_issue(
                    token.location,
                    "%s must not be followed by whitespace" % token.raw_text,
                    True)
                token.fix.ensure_trim_after = True

        elif token.kind in ("KET", "A_KET", "M_KET"):
            if config.active(cfg, "whitespace_brackets") and \
               prev_in_line and ws_before > 0:
                mh.style_issue(
                    token.location,
                    "%s must not be preceeded by whitespace" % token.raw_text,
                    True)
                token.fix.ensure_trim_before = True

        # Corresponds to the old CodeChecker KeywordWhitespace rule
        elif (token.kind == "KEYWORD" and token.value in KEYWORDS_WITH_WS):
            if config.active(cfg, "whitespace_keywords") and \
               next_in_line and ws_after == 0:
                mh.style_issue(token.location,
                               "keyword must be succeeded by whitespace", True)
                token.fix.ensure_ws_after = True

        # Corresponds to the old CodeChecker CommentWhitespace rule
        elif token.kind == "COMMENT":
            if config.active(cfg, "whitespace_comments"):
                comment_char = token.raw_text[0]
                comment_body = token.raw_text.lstrip(comment_char)
                if re.match("^%#[a-zA-Z]", token.raw_text):
                    # Stuff like %#codegen or %#ok are pragmas and should
                    # not be subject to style checks
                    pass

                elif token.raw_text.startswith("%|"):
                    # This is a miss-hit pragma, but we've not
                    # processed it. This is fine.
                    pass

                elif token.block_comment:
                    # Ignore block comments
                    pass

                elif token.raw_text.strip() in ("%s%s" % (cc, cb)
                                                for cc in tbuf.comment_char
                                                for cb in "{}"):
                    # Leave block comment indicators alone
                    pass

                elif re.match("^%# +[a-zA-Z]", token.raw_text):
                    # This looks like a pragma, but there is a spurious
                    # space
                    mh.style_issue(
                        token.location,
                        "MATLAB pragma must not contain whitespace "
                        "between %# and the pragma", True)
                    token.raw_text = "%#" + token.raw_text[2:].strip()

                elif re.match("^% +#[a-zA-Z]", token.raw_text):
                    # This looks like a pragma that got "fixed" before we
                    # fixed our pragma handling
                    mh.style_issue(
                        token.location,
                        "MATLAB pragma must not contain whitespace "
                        "between % and the pragma", True)
                    token.raw_text = "%#" + token.raw_text.split("#", 1)[1]

                elif comment_body and not comment_body.startswith(" "):
                    # Normal comments should contain whitespace
                    mh.style_issue(
                        token.location, "comment body must be separated with "
                        "whitespace from the starting %s" % comment_char, True)
                    token.raw_text = (
                        comment_char *
                        (len(token.raw_text) - len(comment_body)) + " " +
                        comment_body)

                # Make sure we have whitespace before each comment
                if prev_in_line and ws_before == 0:
                    mh.style_issue(token.location,
                                   "comment must be preceeded by whitespace",
                                   True)
                    token.fix.ensure_ws_before = True

        elif token.kind == "CONTINUATION":
            # Make sure we have whitespace before each line continuation
            if config.active(cfg, "whitespace_continuation") and \
               prev_in_line and ws_before == 0:
                mh.style_issue(token.location,
                               "continuation must be preceeded by whitespace",
                               True)
                token.fix.ensure_ws_before = True

            if config.active(cfg, "operator_after_continuation") and \
               next_token and next_token.first_in_line and \
               next_token.kind == "OPERATOR" and \
               next_token.fix.binary_operator:
                # Continuations should not start with operators unless
                # its a unary.
                mh.style_issue(
                    next_token.location,
                    "continuations should not start with binary "
                    "operators")

            if config.active(cfg, "useless_continuation"):
                if next_token and next_token.kind in ("NEWLINE", "COMMENT"):
                    # Continuations followed immediately by a new-line
                    # or comment are not actually helpful at all.
                    mh.style_issue(token.location, "useless line continuation",
                                   True)
                    token.fix.replace_with_newline = True
                elif prev_token and prev_token.fix.statement_terminator:
                    mh.style_issue(token.location, "useless line continuation",
                                   True)
                    token.fix.delete = True

        elif token.kind == "OPERATOR":
            if not config.active(cfg, "operator_whitespace"):
                pass
            elif token.fix.unary_operator:
                if (prev_in_line and ws_before > 0) and \
                   token.value in (".'", "'"):
                    mh.style_issue(
                        token.location,
                        "suffix operator must not be preceeded by"
                        " whitespace", True)
                    token.fix.ensure_trim_before = True
                elif (next_in_line and ws_after > 0) and \
                     token.value not in (".'", "'"):
                    mh.style_issue(
                        token.location,
                        "unary operator must not be followed by"
                        " whitespace", True)
                    token.fix.ensure_trim_after = True
            elif token.fix.binary_operator:
                if token.value in (".^", "^"):
                    if (prev_in_line and ws_before > 0) or \
                       (next_in_line and ws_after > 0):
                        mh.style_issue(
                            token.location, "power binary operator"
                            " must not be surrounded by whitespace", True)
                        token.fix.ensure_trim_before = True
                        token.fix.ensure_trim_after = True
                else:
                    if (prev_in_line and ws_before == 0) or \
                       (next_in_line and ws_after == 0):
                        mh.style_issue(
                            token.location, "non power binary operator"
                            " must be surrounded by whitespace", True)
                        token.fix.ensure_ws_before = True
                        token.fix.ensure_ws_after = True

            if config.active(cfg, "implicit_shortcircuit") and \
               token.value in ("&", "|") and \
               token.ast_link and \
               isinstance(token.ast_link, Binary_Logical_Operation) and \
               token.ast_link.short_circuit:
                # This rule is *disabled* for now since it does not
                # work in all circumstances. Curiously, this bug is
                # shared by mlint which also mis-classifies & when
                # applied to arrays.
                #
                # To fix this we need to perform semantic analysis and
                # type inference. We're leaving this in for
                # compatibility with miss_hit.cfg files that contain
                # reference to this rules.
                #
                # mh.style_issue(token.location,
                #                "implicit short-circuit operation due to"
                #                " expression being contained in "
                #                " if/while guard",
                #                True)
                # token.fix.make_shortcircuit_explicit = True
                pass

        elif token.kind == "ANNOTATION":
            if config.active(cfg, "annotation_whitespace"):
                token.fix.ensure_ws_after = True

                if next_in_line and ws_after == 0:
                    mh.style_issue(
                        token.location,
                        "annotation indication must be succeeded"
                        " by whitespace", True)

        elif token.kind == "NEWLINE":
            if n == 0 and config.active(cfg, "no_starting_newline"):
                # Files should not *start* with newline(s)
                mh.style_issue(token.location,
                               "files should not start with a newline", True)
                token.fix.delete = True

        # Check some specific problems with continuations
        if token.fix.flag_continuations and \
           next_in_line and next_in_line.kind == "CONTINUATION":
            fixed = False
            token.fix.add_newline = False
            if config.active(cfg, "dangerous_continuation"):
                next_in_line.fix.replace_with_newline = True
                fixed = True
            mh.style_issue(next_in_line.location,
                           "this continuation is dangerously misleading",
                           fixed)

        # Complain about indentation
        if config.active(cfg, "indentation") and token.kind != "NEWLINE":
            if token.first_in_line and not token.block_comment:
                if token.first_in_statement:
                    if token.ast_link:
                        current_indent = token.ast_link.get_indentation()
                    elif enclosing_ast:
                        current_indent = enclosing_ast.get_indentation() + 1
                    offset = 0

                else:
                    # This is a continued line. We try to preserve
                    # the offset. We work out how much extra space
                    # this token has based on the statement
                    # starting token.
                    offset = token.location.col_start - \
                        statement_start_token.location.col_start

                    # If positive, we can just add it. If 0 or
                    # negative, then we add 1/2 tabs to continue
                    # the line, since previously it was not offset
                    # at all.
                    if offset <= 0:
                        offset = cfg["tab_width"] // 2

                correct_spaces = cfg["tab_width"] * current_indent + offset
                token.fix.correct_indent = correct_spaces

                if token.location.col_start != correct_spaces:
                    mh.style_issue(
                        token.location, "indentation not correct, should be"
                        " %u spaces, not %u" %
                        (correct_spaces, token.location.col_start), True)