Skip to content

Commit

Permalink
Fixed unbound global variables in `pywin.dialogs.ideoptions.OptionsPr…
Browse files Browse the repository at this point in the history
…opPage`'s `OnFormat*` methods + re-enable pyright's reportUnboundVariable (mhammond#2283)
  • Loading branch information
Avasam authored Nov 13, 2024
1 parent 68aaa09 commit 0023fd3
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 147 deletions.
17 changes: 7 additions & 10 deletions Pythonwin/pywin/dialogs/ideoptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,26 +114,23 @@ def ChangeFormat(self, fmtAttribute, fmt):
def OnFormatTitle(self, command, code):
fmt = self.GetFormat(interact.formatTitle)
if fmt:
formatTitle = fmt
interact.formatTitle = fmt
interact.SaveFontPreferences()

def OnFormatInput(self, command, code):
global formatInput
fmt = self.GetFormat(formatInput)
fmt = self.GetFormat(interact.formatInput)
if fmt:
formatInput = fmt
interact.formatInput = fmt
interact.SaveFontPreferences()

def OnFormatOutput(self, command, code):
global formatOutput
fmt = self.GetFormat(formatOutput)
fmt = self.GetFormat(interact.formatOutput)
if fmt:
formatOutput = fmt
interact.formatOutput = fmt
interact.SaveFontPreferences()

def OnFormatError(self, command, code):
global formatOutputError
fmt = self.GetFormat(formatOutputError)
fmt = self.GetFormat(interact.formatOutputError)
if fmt:
formatOutputError = fmt
interact.formatOutputError = fmt
interact.SaveFontPreferences()
272 changes: 137 additions & 135 deletions adodbapi/process_connect_string.py
Original file line number Diff line number Diff line change
@@ -1,135 +1,137 @@
"""a clumsy attempt at a macro language to let the programmer execute code on the server (ex: determine 64bit)"""

from . import is64bit


def macro_call(macro_name, args, kwargs):
"""allow the programmer to perform limited processing on the server by passing macro names and args
:new_key - the key name the macro will create
:args[0] - macro name
:args[1:] - any arguments
:code - the value of the keyword item
:kwargs - the connection keyword dictionary. ??key has been removed
--> the value to put in for kwargs['name'] = value
"""
if isinstance(args, (str, str)):
args = [
args
] # the user forgot to pass a sequence, so make a string into args[0]
new_key = args[0]
try:
if macro_name == "is64bit":
if is64bit.Python(): # if on 64 bit Python
return new_key, args[1] # return first argument
else:
try:
return new_key, args[2] # else return second argument (if defined)
except IndexError:
return new_key, "" # else return blank

elif (
macro_name == "getuser"
): # get the name of the user the server is logged in under
if not new_key in kwargs:
import getpass

return new_key, getpass.getuser()

elif macro_name == "getnode": # get the name of the computer running the server
import platform

try:
return new_key, args[1] % platform.node()
except IndexError:
return new_key, platform.node()

elif macro_name == "getenv": # expand the server's environment variable args[1]
try:
dflt = args[2] # if not found, default from args[2]
except IndexError: # or blank
dflt = ""
return new_key, os.environ.get(args[1], dflt)

elif macro_name == "auto_security":
if (
not "user" in kwargs or not kwargs["user"]
): # missing, blank, or Null username
return new_key, "Integrated Security=SSPI"
return new_key, "User ID=%(user)s; Password=%(password)s" % kwargs

elif (
macro_name == "find_temp_test_path"
): # helper function for testing ado operation -- undocumented
import os
import tempfile

return new_key, os.path.join(
tempfile.gettempdir(), "adodbapi_test", args[1]
)

raise ValueError(f"Unknown connect string macro={macro_name}")
except:
raise ValueError(f"Error in macro processing {macro_name} {args!r}")


def process(
args, kwargs, expand_macros=False
): # --> connection string with keyword arguments processed.
"""attempts to inject arguments into a connection string using Python "%" operator for strings
co: adodbapi connection object
args: positional parameters from the .connect() call
kvargs: keyword arguments from the .connect() call
"""
try:
dsn = args[0]
except IndexError:
dsn = None
# as a convenience the first argument may be django settings
if isinstance(dsn, dict):
kwargs.update(dsn)
# the connection string is passed to the connection as part of the keyword dictionary
elif dsn:
kwargs["connection_string"] = dsn
try:
a1 = args[1]
except IndexError:
a1 = None
# historically, the second positional argument might be a timeout value
if isinstance(a1, int):
kwargs["timeout"] = a1
# if the second positional argument is a string, then it is user
elif isinstance(a1, str):
kwargs["user"] = a1
# if the second positional argument is a dictionary, use it as keyword arguments, too
elif isinstance(a1, dict):
kwargs.update(a1)
try:
kwargs["password"] = args[2] # the third positional argument is password
kwargs["host"] = args[3] # the fourth positional argument is host name
kwargs["database"] = args[4] # the fifth positional argument is database name
except IndexError:
pass

# make sure connection string is defined somehow
if not "connection_string" in kwargs:
try: # perhaps 'dsn' was defined
kwargs["connection_string"] = kwargs["dsn"]
except KeyError:
try: # as a last effort, use the "host" keyword
kwargs["connection_string"] = kwargs["host"]
except KeyError:
raise TypeError("Must define 'connection_string' for ado connections")
if expand_macros:
for kwarg in list(kwargs.keys()):
if kwarg.startswith("macro_"): # If a key defines a macro
macro_name = kwarg[6:] # name without the "macro_"
macro_code = kwargs.pop(
kwarg
) # we remove the macro_key and get the code to execute
new_key, rslt = macro_call(
macro_name, macro_code, kwargs
) # run the code in the local context
kwargs[new_key] = rslt # put the result back in the keywords dict
return kwargs
"""a clumsy attempt at a macro language to let the programmer execute code on the server (ex: determine 64bit)"""

from . import is64bit


def macro_call(macro_name, args, kwargs):
"""allow the programmer to perform limited processing on the server by passing macro names and args
:new_key - the key name the macro will create
:args[0] - macro name
:args[1:] - any arguments
:code - the value of the keyword item
:kwargs - the connection keyword dictionary. ??key has been removed
--> the value to put in for kwargs['name'] = value
"""
if isinstance(args, (str, str)):
args = [
args
] # the user forgot to pass a sequence, so make a string into args[0]
new_key = args[0]
try:
if macro_name == "is64bit":
if is64bit.Python(): # if on 64 bit Python
return new_key, args[1] # return first argument
else:
try:
return new_key, args[2] # else return second argument (if defined)
except IndexError:
return new_key, "" # else return blank

elif (
macro_name == "getuser"
): # get the name of the user the server is logged in under
if not new_key in kwargs:
import getpass

return new_key, getpass.getuser()

elif macro_name == "getnode": # get the name of the computer running the server
import platform

try:
return new_key, args[1] % platform.node()
except IndexError:
return new_key, platform.node()

elif macro_name == "getenv": # expand the server's environment variable args[1]
import os

try:
dflt = args[2] # if not found, default from args[2]
except IndexError: # or blank
dflt = ""
return new_key, os.environ.get(args[1], dflt)

elif macro_name == "auto_security":
if (
not "user" in kwargs or not kwargs["user"]
): # missing, blank, or Null username
return new_key, "Integrated Security=SSPI"
return new_key, "User ID=%(user)s; Password=%(password)s" % kwargs

elif (
macro_name == "find_temp_test_path"
): # helper function for testing ado operation -- undocumented
import os
import tempfile

return new_key, os.path.join(
tempfile.gettempdir(), "adodbapi_test", args[1]
)

raise ValueError(f"Unknown connect string macro={macro_name}")
except:
raise ValueError(f"Error in macro processing {macro_name} {args!r}")


def process(
args, kwargs, expand_macros=False
): # --> connection string with keyword arguments processed.
"""attempts to inject arguments into a connection string using Python "%" operator for strings
co: adodbapi connection object
args: positional parameters from the .connect() call
kvargs: keyword arguments from the .connect() call
"""
try:
dsn = args[0]
except IndexError:
dsn = None
# as a convenience the first argument may be django settings
if isinstance(dsn, dict):
kwargs.update(dsn)
# the connection string is passed to the connection as part of the keyword dictionary
elif dsn:
kwargs["connection_string"] = dsn
try:
a1 = args[1]
except IndexError:
a1 = None
# historically, the second positional argument might be a timeout value
if isinstance(a1, int):
kwargs["timeout"] = a1
# if the second positional argument is a string, then it is user
elif isinstance(a1, str):
kwargs["user"] = a1
# if the second positional argument is a dictionary, use it as keyword arguments, too
elif isinstance(a1, dict):
kwargs.update(a1)
try:
kwargs["password"] = args[2] # the third positional argument is password
kwargs["host"] = args[3] # the fourth positional argument is host name
kwargs["database"] = args[4] # the fifth positional argument is database name
except IndexError:
pass

# make sure connection string is defined somehow
if not "connection_string" in kwargs:
try: # perhaps 'dsn' was defined
kwargs["connection_string"] = kwargs["dsn"]
except KeyError:
try: # as a last effort, use the "host" keyword
kwargs["connection_string"] = kwargs["host"]
except KeyError:
raise TypeError("Must define 'connection_string' for ado connections")
if expand_macros:
for kwarg in list(kwargs.keys()):
if kwarg.startswith("macro_"): # If a key defines a macro
macro_name = kwarg[6:] # name without the "macro_"
macro_code = kwargs.pop(
kwarg
) # we remove the macro_key and get the code to execute
new_key, rslt = macro_call(
macro_name, macro_code, kwargs
) # run the code in the local context
kwargs[new_key] = rslt # put the result back in the keywords dict
return kwargs
2 changes: 0 additions & 2 deletions pyrightconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@
"reportOptionalSubscript": "warning",
// Needs fixes in types-pywin32 and requires Python 3.8 to annotate ambiguous global variables
"reportUnnecessaryComparison": "warning",
// TODO: Leave Unbound its own PR(s)
"reportUnboundVariable": "warning",
// Too many dynamically generated modules. This will require type stubs to properly fix.
"reportMissingImports": "warning",
// IDEM, but happens when pywin32 is not in site-packages but module is found from typeshed.
Expand Down

0 comments on commit 0023fd3

Please sign in to comment.