Hướng dẫn python 3 has_key alternative

I try to install Auto-SelfControl and got stuck when executing this command:

sudo /usr/bin/python auto-selfcontrol.py

It shows the error:

AttributeError: 'dict' object has no attribute 'has_key'

I'm searching for solutions and end up with replacing has_key for in operator but as I only know the basics of python, the code is quite complex for me.

There're 3 places where has_key have been used, can you help me change it so I can run with python3?

1.

def check_if_running(username):
""" checks if self-control is already running. """
defaults = get_selfcontrol_settings(username)
return defaults.has_key("BlockStartedDate") and not NSDate.distantFuture().isEqualToDate_(defaults["BlockStartedDate"])

2-4.

def check_config(config):
""" checks whether the config file is correct """
if not config.has_key("username"):
    exit_with_error("No username specified in config.")
if config["username"] not in get_osx_usernames():
    exit_with_error(
            "Username '{username}' unknown.\nPlease use your OSX username instead.\n" \
            "If you have trouble finding it, just enter the command 'whoami'\n" \
            "in your terminal.".format(
                    username=config["username"]))
if not config.has_key("selfcontrol-path"):
    exit_with_error("The setting 'selfcontrol-path' is required and must point to the location of SelfControl.")
if not os.path.exists(config["selfcontrol-path"]):
    exit_with_error(
            "The setting 'selfcontrol-path' does not point to the correct location of SelfControl. " \
            "Please make sure to use an absolute path and include the '.app' extension, " \
            "e.g. /Applications/SelfControl.app")
if not config.has_key("block-schedules"):
    exit_with_error("The setting 'block-schedules' is required.")
if len(config["block-schedules"]) == 0:
    exit_with_error("You need at least one schedule in 'block-schedules'.")
if config.get("host-blacklist", None) is None:
    print("WARNING:")
    msg = "It is not recommended to directly use SelfControl's blacklist. Please use the 'host-blacklist' " \
          "setting instead."
    print(msg)
    syslog.syslog(syslog.LOG_WARNING, msg)

Hướng dẫn python 3 has_key alternative

Morse

7,2766 gold badges35 silver badges62 bronze badges

asked Jan 23, 2019 at 23:24

6

While the piecemeal solutions in the other answers will work, that approach is flawed simply because it's too easy to make a small mistake, miss a place that needs fixing, etc. The better solution is to just use the 2to3 converter. You could fix all of your files in one fell swoop with:

$ 2to3 -f has_key -w auto-selfcontrol.py

That only runs the has_key fixer which converts from dict.has_key(key) to key in dict. Sure you could make the fix yourself, but this is a case where simple programmatic fixers work just fine. You might just want to run it without -f has_key so it applies all the fixers at once, in case there are any other breaking changes that apply between Py2 and Py3.

2to3 handles just about everything automatically, with the exception of Py2 str type changes (where it's a code logic decision on whether a given str literal should be bytes or str in Py3) and integer division (where / might need to change to //, based on whether the computation is logically floating point division or floor division). But for has_key, it's pretty reliable.

answered Jan 24, 2019 at 1:18

Hướng dẫn python 3 has_key alternative

ShadowRangerShadowRanger

132k12 gold badges168 silver badges245 bronze badges

0

A formal source for the solution is here: https://portingguide.readthedocs.io/en/latest/dicts.html

The TL;DR is this:

some_dict.has_key('some key')

Is now:

'some key' in some_dict

So, in your code:

return defaults.has_key("BlockStartedDate") and not NSDate.distantFuture().isEqualToDate_(defaults["BlockStartedDate"])

Becomes:

return "BlockStartedDate" in defaults and not NSDate.distantFuture().isEqualToDate_(defaults["BlockStartedDate"])

Similarly, lines like:

if not config.has_key("selfcontrol-path"):
    # do something

Become like:

if "selfcontrol-path" not in config:
    # do something

Note that you could also write if not "selfcontrol-path" in config: but the example given above is considered more Pythonic and should be preferred.

answered Jan 24, 2019 at 0:39

Hướng dẫn python 3 has_key alternative

GrismarGrismar

24k4 gold badges29 silver badges49 bronze badges

Tested in python3.7.

   tmp = {'a':1, 'b':2, 'c':3}
   print(tmp.__contains__('a')) #True

answered May 29, 2019 at 8:20

qloveshmilyqloveshmily

9318 silver badges5 bronze badges

Replace as follows

1.

def check_if_running(username):
""" checks if self-control is already running. """
defaults = get_selfcontrol_settings(username)
return "BlockStartedDate" in defaults and not NSDate.distantFuture().isEqualToDate_(defaults["BlockStartedDate"])

2-4.

def check_config(config):
""" checks whether the config file is correct """
if not "username" in config:
    exit_with_error("No username specified in config.")
if config["username"] not in get_osx_usernames():
    exit_with_error(
            "Username '{username}' unknown.\nPlease use your OSX username instead.\n" \
            "If you have trouble finding it, just enter the command 'whoami'\n" \
            "in your terminal.".format(
                    username=config["username"]))
if not "selfcontrol-path" in config:
    exit_with_error("The setting 'selfcontrol-path' is required and must point to the location of SelfControl.")
if not os.path.exists(config["selfcontrol-path"]):
    exit_with_error(
            "The setting 'selfcontrol-path' does not point to the correct location of SelfControl. " \
            "Please make sure to use an absolute path and include the '.app' extension, " \
            "e.g. /Applications/SelfControl.app")
if not "block-schedules" in config:
    exit_with_error("The setting 'block-schedules' is required.")
if len(config["block-schedules"]) == 0:
    exit_with_error("You need at least one schedule in 'block-schedules'.")
if config.get("host-blacklist", None) is None:
    print("WARNING:")
    msg = "It is not recommended to directly use SelfControl's blacklist. Please use the 'host-blacklist' " \
          "setting instead."
    print(msg)
    syslog.syslog(syslog.LOG_WARNING, msg)

answered Jan 24, 2019 at 0:29

VaibhavVaibhav

4454 silver badges7 bronze badges