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

ImportError: cannot import name 'properties' from 'keyring.util' #33

Open
mrzoops opened this issue Jan 2, 2024 · 3 comments
Open

ImportError: cannot import name 'properties' from 'keyring.util' #33

mrzoops opened this issue Jan 2, 2024 · 3 comments
Assignees

Comments

@mrzoops
Copy link

mrzoops commented Jan 2, 2024

Expected behavior

Bot starts

...

Actual behavior

Error:

ImportError: cannot import name 'properties' from 'keyring.util'
(C:\Python310\lib\site-packages\keyring\util_init_.py)

...

To Reproduce

  1. ... Install bot
  2. ... open CMD
  3. ... run 3b-bot

Screenshots

System information

  • OS Platform (e.g., macOS Mojave):
  • win11
  • BestBuyBulletBot version:
  • Python version: 3.12.1

Additional context

@platinumraceworx
Copy link

did this ever get solved? im having the same issue here.

@winters27
Copy link

The error was caused by an outdated import from keyring.util.properties. Here's a fix that worked for me:

Replace the contents of user_data.py with the following code:

import os
import sys
from getpass import getpass

from keyring.errors import PasswordDeleteError
# Removed: from keyring.util import properties
from keyrings.cryptfile.cryptfile import CryptFileKeyring
from keyrings.cryptfile.file_base import FileBacked

from best_buy_bullet_bot.data import SHARED_DIR
from best_buy_bullet_bot.utils import Colors, yes_or_no

EMAIL_VAR = "BB_EMAIL"
PASS_VAR = "BB_PASS"
CVV_VAR = "BB_CVV"

# Custom property decorator to replace the removed import
class NonDataProperty:
    def __init__(self, fget):
        self.fget = fget

    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        return self.fget(obj)

@NonDataProperty
def file_path(self):
    return os.path.join(SHARED_DIR, self.filename)

FileBacked.file_path = file_path

SERVICE_ID = "3B_BOT"
KR = CryptFileKeyring()

# Rest of the file remains unchanged
def set_access_pass(access_pass):
    KR._keyring_key = access_pass

def authenticate():
    attempts = 0
    while True:
        try:
            KR.keyring_key
            return
        except ValueError:
            if str(KR._keyring_key).strip() == "":
                sys.exit()

            attempts += 1
            if attempts >= 3:
                print("Too many attempts, please try again later.")
                sys.exit()

            print("Sorry, try again.")
            KR._keyring_key = None

def _get_cred(name, default_value):
    cred = KR.get_password(SERVICE_ID, name)
    return cred if cred is not None else default_value

def get_creds(default_value=""):
    authenticate()
    return [_get_cred(var, default_value) for var in [EMAIL_VAR, PASS_VAR, CVV_VAR]]

def _get_input(prompt):
    while True:
        value = input(prompt)

        if yes_or_no("Continue (y/n): "):
            return value

def set_creds():
    authenticate()
    KR.set_password(SERVICE_ID, EMAIL_VAR, _get_input("Email: "))

    print()
    while True:
        password = getpass("Best Buy password: ")
        confirm_pass = getpass("Confirm password: ")
        if password == confirm_pass:
            break
        print("Passwords didn't match! Try again.")
    KR.set_password(SERVICE_ID, PASS_VAR, password)

    print()
    KR.set_password(SERVICE_ID, CVV_VAR, _get_input("CVV: "))
    Colors.print("Successfully updated credentials!", properties=["success"])

def print_creds():
    email, password, cvv = get_creds(Colors.str("EMPTY", ["fail"]))
    print("Email:", email)
    print("Password:", password)
    print("CVV:", cvv)

def clear_creds():
    for name in [EMAIL_VAR, PASS_VAR, CVV_VAR]:
        try:
            KR.delete_password(SERVICE_ID, name)
        except PasswordDeleteError:
            pass
    Colors.print("Credentials cleared!\n", properties=["success", "bold"])

    if yes_or_no("Would you like to reset your password (y/n): "):
        os.remove(KR.file_path)
        KR.keyring_key

@bensenx
Copy link

bensenx commented Jan 16, 2025

The error was caused by an outdated import from keyring.util.properties. Here's a fix that worked for me:

Replace the contents of user_data.py with the following code:

import os
import sys
from getpass import getpass

from keyring.errors import PasswordDeleteError
# Removed: from keyring.util import properties
from keyrings.cryptfile.cryptfile import CryptFileKeyring
from keyrings.cryptfile.file_base import FileBacked

from best_buy_bullet_bot.data import SHARED_DIR
from best_buy_bullet_bot.utils import Colors, yes_or_no

EMAIL_VAR = "BB_EMAIL"
PASS_VAR = "BB_PASS"
CVV_VAR = "BB_CVV"

# Custom property decorator to replace the removed import
class NonDataProperty:
    def __init__(self, fget):
        self.fget = fget

    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        return self.fget(obj)

@NonDataProperty
def file_path(self):
    return os.path.join(SHARED_DIR, self.filename)

FileBacked.file_path = file_path

SERVICE_ID = "3B_BOT"
KR = CryptFileKeyring()

# Rest of the file remains unchanged
def set_access_pass(access_pass):
    KR._keyring_key = access_pass

def authenticate():
    attempts = 0
    while True:
        try:
            KR.keyring_key
            return
        except ValueError:
            if str(KR._keyring_key).strip() == "":
                sys.exit()

            attempts += 1
            if attempts >= 3:
                print("Too many attempts, please try again later.")
                sys.exit()

            print("Sorry, try again.")
            KR._keyring_key = None

def _get_cred(name, default_value):
    cred = KR.get_password(SERVICE_ID, name)
    return cred if cred is not None else default_value

def get_creds(default_value=""):
    authenticate()
    return [_get_cred(var, default_value) for var in [EMAIL_VAR, PASS_VAR, CVV_VAR]]

def _get_input(prompt):
    while True:
        value = input(prompt)

        if yes_or_no("Continue (y/n): "):
            return value

def set_creds():
    authenticate()
    KR.set_password(SERVICE_ID, EMAIL_VAR, _get_input("Email: "))

    print()
    while True:
        password = getpass("Best Buy password: ")
        confirm_pass = getpass("Confirm password: ")
        if password == confirm_pass:
            break
        print("Passwords didn't match! Try again.")
    KR.set_password(SERVICE_ID, PASS_VAR, password)

    print()
    KR.set_password(SERVICE_ID, CVV_VAR, _get_input("CVV: "))
    Colors.print("Successfully updated credentials!", properties=["success"])

def print_creds():
    email, password, cvv = get_creds(Colors.str("EMPTY", ["fail"]))
    print("Email:", email)
    print("Password:", password)
    print("CVV:", cvv)

def clear_creds():
    for name in [EMAIL_VAR, PASS_VAR, CVV_VAR]:
        try:
            KR.delete_password(SERVICE_ID, name)
        except PasswordDeleteError:
            pass
    Colors.print("Credentials cleared!\n", properties=["success", "bold"])

    if yes_or_no("Would you like to reset your password (y/n): "):
        os.remove(KR.file_path)
        KR.keyring_key

That works for me, thanks, pay attention that you have to locate the user_data.py under the Lib\site-packages\best_buy_bullet_bot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants