Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code marked unreachable after start_transaction() from mysql.connector #940

Closed
axxelG opened this issue Feb 11, 2021 · 9 comments
Closed
Labels
waiting for user response Requires more information from user

Comments

@axxelG
Copy link

axxelG commented Feb 11, 2021

Environment data

  • Language Server version: 2021.2.0 (pyright e278f28d)
  • OS and version: Windows 10 18363.1139 / WSL2 Debian GNU/Linux 10 (buster)
  • Python version (& distribution if applicable, e.g. Anaconda): 3.7.3
  • mysql-connector: 2.2.9

Expected behaviour

Do not mark code following start_transaction() as unreachable

Actual behaviour

Code following start_transaction() is marked as unreachable

Logs

> ~/.cache/pypoetry/virtualenvs/testapp-e3-vEaIb-py3.7/bin/python ~/.vscode-server/extensions/ms-python.python-2021.1.502429796/pythonFiles/pyvsc-run-isolated.py mypy --ignore-missing-imports --follow-imports=silent --show-column-numbers /mnt/c/Users/myusername/igrepos/testapp/testapp/test_pylance_bug.py
cwd: /mnt/c/Users/myusername/igrepos/testapp
> ~/.cache/pypoetry/virtualenvs/testapp-e3-vEaIb-py3.7/bin/python ~/.vscode-server/extensions/ms-python.python-2021.1.502429796/pythonFiles/pyvsc-run-isolated.py mypy --ignore-missing-imports --follow-imports=silent --show-column-numbers /mnt/c/Users/myusername/igrepos/testapp/testapp/test_pylance_bug.py
cwd: /mnt/c/Users/myusername/igrepos/testapp
> ~/.cache/pypoetry/virtualenvs/testapp-e3-vEaIb-py3.7/bin/python ~/.vscode-server/extensions/ms-python.python-2021.1.502429796/pythonFiles/pyvsc-run-isolated.py pycodestyle --format=%(row)d,%(col)d,%(code).1s,%(code)s:%(text)s /mnt/c/Users/myusername/igrepos/testapp/testapp/test_pylance_bug.py
cwd: /mnt/c/Users/myusername/igrepos/testapp
> ~/.cache/pypoetry/virtualenvs/testapp-e3-vEaIb-py3.7/bin/python ~/.vscode-server/extensions/ms-python.python-2021.1.502429796/pythonFiles/pyvsc-run-isolated.py pycodestyle --format=%(row)d,%(col)d,%(code).1s,%(code)s:%(text)s /mnt/c/Users/myusername/igrepos/testapp/testapp/test_pylance_bug.py
cwd: /mnt/c/Users/myusername/igrepos/testapp
> ~/.cache/pypoetry/virtualenvs/testapp-e3-vEaIb-py3.7/bin/python ~/.vscode-server/extensions/ms-python.python-2021.1.502429796/pythonFiles/pyvsc-run-isolated.py pylint --disable=all --enable=F,unreachable,duplicate-key,unnecessary-semicolon,global-variable-not-assigned,unused-variable,unused-wildcard-import,binary-op-exception,bad-format-string,anomalous-backslash-in-string,bad-open-mode,E0001,E0011,E0012,E0100,E0101,E0102,E0103,E0104,E0105,E0107,E0108,E0110,E0111,E0112,E0113,E0114,E0115,E0116,E0117,E0118,E0202,E0203,E0211,E0213,E0236,E0237,E0238,E0239,E0240,E0241,E0301,E0302,E0303,E0401,E0402,E0601,E0602,E0603,E0604,E0611,E0632,E0633,E0701,E0702,E0703,E0704,E0710,E0711,E0712,E1003,E1101,E1102,E1111,E1120,E1121,E1123,E1124,E1125,E1126,E1127,E1128,E1129,E1130,E1131,E1132,E1133,E1134,E1135,E1136,E1137,E1138,E1139,E1200,E1201,E1205,E1206,E1300,E1301,E1302,E1303,E1304,E1305,E1306,E1310,E1700,E1701 --msg-template='{line},{column},{category},{symbol}:{msg}' --reports=n --output-format=text /mnt/c/Users/myusername/igrepos/testapp/testapp/test_pylance_bug.py
cwd: /mnt/c/Users/myusername/igrepos/testapp
> ~/.cache/pypoetry/virtualenvs/testapp-e3-vEaIb-py3.7/bin/python ~/.vscode-server/extensions/ms-python.python-2021.1.502429796/pythonFiles/pyvsc-run-isolated.py pylint --disable=all --enable=F,unreachable,duplicate-key,unnecessary-semicolon,global-variable-not-assigned,unused-variable,unused-wildcard-import,binary-op-exception,bad-format-string,anomalous-backslash-in-string,bad-open-mode,E0001,E0011,E0012,E0100,E0101,E0102,E0103,E0104,E0105,E0107,E0108,E0110,E0111,E0112,E0113,E0114,E0115,E0116,E0117,E0118,E0202,E0203,E0211,E0213,E0236,E0237,E0238,E0239,E0240,E0241,E0301,E0302,E0303,E0401,E0402,E0601,E0602,E0603,E0604,E0611,E0632,E0633,E0701,E0702,E0703,E0704,E0710,E0711,E0712,E1003,E1101,E1102,E1111,E1120,E1121,E1123,E1124,E1125,E1126,E1127,E1128,E1129,E1130,E1131,E1132,E1133,E1134,E1135,E1136,E1137,E1138,E1139,E1200,E1201,E1205,E1206,E1300,E1301,E1302,E1303,E1304,E1305,E1306,E1310,E1700,E1701 --msg-template='{line},{column},{category},{symbol}:{msg}' --reports=n --output-format=text /mnt/c/Users/myusername/igrepos/testapp/testapp/test_pylance_bug.py
cwd: /mnt/c/Users/myusername/igrepos/testapp
##########Linting Output - pycodestyle##########
##########Linting Output - mypy##########
Success: no issues found in 1 source file
##########Linting Output - pylint##########

--------------------------------------------------------------------
Your code has been rated at 10.00/10 (previous run: 10.00/10, +0.00)

Code Snippet / Additional information

image

from mysql.connector import connect, MySQLConnection


connection = connect(
    user="user",
    host='localhost',
)


def fetch_my_name(connection: MySQLConnection) -> str:
    connection.start_transaction()
    cur = connection.cursor()
    cur.execute('SELECT @@hostname')
    result = cur.fetchone()
    cur.close()
    connection.commit()
    return result[0]

This issue was mentioned by @QuestofIranon in a comment on #31 and he/she was asked to create a separate ticket but I could not find one.

@axxelG
Copy link
Author

axxelG commented Feb 11, 2021

start_transaction() in mysql.connector does not have an annotation or return type. Is this fixable by pylance or have this to be fixed in mysql.connector?

    @abstractmethod
    def rollback(self):
        """Rollback current transaction"""
        pass

    def start_transaction(self, consistent_snapshot=False,
                          isolation_level=None, readonly=None):
        """Start a transaction

        This method explicitly starts a transaction sending the
        START TRANSACTION statement to the MySQL server. You can optionally
        set whether there should be a consistent snapshot, which
        isolation level you need or which access mode i.e. READ ONLY or
        READ WRITE.

        For example, to start a transaction with isolation level SERIALIZABLE,
        you would do the following:
            >>> cnx = mysql.connector.connect(..)
            >>> cnx.start_transaction(isolation_level='SERIALIZABLE')

        Raises ProgrammingError when a transaction is already in progress
        and when ValueError when isolation_level specifies an Unknown
        level.
        """
        if self.in_transaction:
            raise errors.ProgrammingError("Transaction already in progress")

        if isolation_level:
            level = isolation_level.strip().replace('-', ' ').upper()
            levels = ['READ UNCOMMITTED', 'READ COMMITTED', 'REPEATABLE READ',
                      'SERIALIZABLE']

            if level not in levels:
                raise ValueError(
                    'Unknown isolation level "{0}"'.format(isolation_level))

            self._execute_query(
                "SET TRANSACTION ISOLATION LEVEL {0}".format(level))

        if readonly is not None:
            if self._server_version < (5, 6, 5):
                raise ValueError(
                    "MySQL server version {0} does not support "
                    "this feature".format(self._server_version))

            if readonly:
                access_mode = 'READ ONLY'
            else:
                access_mode = 'READ WRITE'
            self._execute_query(
                "SET TRANSACTION {0}".format(access_mode))

        query = "START TRANSACTION"
        if consistent_snapshot:
            query += " WITH CONSISTENT SNAPSHOT"
        self.cmd_query(query)

@jakebailey
Copy link
Member

When you hover start_transaction, what do you get?

I'm thinking that this does need an annotation, e.g. -> None.

@jakebailey jakebailey added waiting for user response Requires more information from user and removed triage labels Feb 11, 2021
@axxelG
Copy link
Author

axxelG commented Feb 11, 2021

Answer to your question: (method) start_transaction: (consistent_snapshot=False, isolation_level=None, readonly=None) -> None + the docstring. I'm pretty sure it was something like -> NoReturn earlier today.

More important: I cannot reproduce the behavior anymore. Between my last (failing) test an now I just put my PC to sleep and came back now to see that it works.

The best explanation I have is that an update was prepared. I don't know how it was effective before I restarted VS Code but I guess we won't find out.

Timeline what happened:

  1. Saw the wrong "unreachable code"
  2. Restarted VS Code + other investigations and tests.
  3. Created test case a new file
  4. Created issue
  5. Deleted the file with the test case, did some unrelated code changes, rebases, ...
  6. Put my PC to sleep
  7. Came back
  8. Recreated the test case (Copied from my Github issue)
  9. Could not reproduce
  10. Checkt what is shown if I hover over the function
  11. Saw the hint to restart VS Code to install an update
  12. Did the restart, updates were installed.
  13. Still everything fine.

Maybe my lengthy explanation helps you if you see similar cases.

From my side this issue can be closed.

@axxelG
Copy link
Author

axxelG commented Feb 11, 2021

Oh and thank you for your very quick reply!

@jakebailey
Copy link
Member

Did VS Code update you to a newer version of Pylance, by chance?

The issue is that it was inferred as NoReturn, which means "i don't return" and therefore anything below the call was marked as unreachable. This can happen with libraries where they are untyped and have code flow that produces paths like that.

@axxelG
Copy link
Author

axxelG commented Feb 11, 2021

Looks like it did. I have two versions in my extensions folder.

ls -lah ~/.vscode-server/extensions/
...
drwxr-xr-x  4 axx axx 4.0K Feb 11 18:04 ms-python.vscode-pylance-2021.2.1
drwxr-xr-x  4 axx axx 4.0K Feb 11 20:30 ms-python.vscode-pylance-2021.2.2
...

The file from 20:30 obviously comes from the update I did half an hour ago. The file from 18:04 was created in the middle of my work - roughly around the time I saw the issue.
Remark: I created this issue with Language Server version: 2021.2.0 (pyright e278f28d)

@axxelG
Copy link
Author

axxelG commented Feb 11, 2021

Directly after writing my last comment:

[Info  - 8:30:28 PM] Pylance language server 2021.2.1 (pyright 9c1f243c) starting

After restarting VS Code (No warning that a restart is needed was shown)

[Info  - 9:08:42 PM] Pylance language server 2021.2.2 (pyright 8ca2c14a) starting

I guess we can be pretty sure that my issue was somehow related to updates.

@axxelG
Copy link
Author

axxelG commented Feb 11, 2021

Now the older version in the extensions folder is gone. It looks like I got at least three updates for the Language Server today.

Thinking a bit more about the root cause I got annother idea:
I added pycodestyle = "^2.6.0" via poetry today. Could that have triggered a step by step installation of multiple pylance versions?

FYI: I will be afk until tomorrow.

@jakebailey
Copy link
Member

I'm going to close this as I think you said you couldn't reproduce it anymore (and it's been a good month). If it reappears, we can reopen and take a look.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
waiting for user response Requires more information from user
Projects
None yet
Development

No branches or pull requests

2 participants