Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jaraco/keyring
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v25.2.1
Choose a base ref
...
head repository: jaraco/keyring
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v25.3.0
Choose a head ref
  • 20 commits
  • 8 files changed
  • 4 contributors

Commits on Mar 23, 2024

  1. Add a test capturing the missed expectation. Ref #668.

    jaraco committed Mar 23, 2024
    Copy the full SHA
    bc34083 View commit details
  2. Mark the test as xfail where it's failing (Windows).

    jaraco committed Mar 23, 2024
    Copy the full SHA
    5d117cb View commit details

Commits on May 31, 2024

  1. Copy the full SHA
    a595a0f View commit details

Commits on Jun 21, 2024

  1. Copy the full SHA
    c9729e1 View commit details
  2. Merge https://github.com/jaraco/skeleton

    # Conflicts:
    #	pyproject.toml
    jaraco committed Jun 21, 2024
    Copy the full SHA
    afe0abd View commit details

Commits on Jun 25, 2024

  1. Fix pylint warning unspecified-encoding

    RatishT committed Jun 25, 2024
    Copy the full SHA
    c9cfc7d View commit details

Commits on Jun 30, 2024

  1. Add a test to cover core.disable. Reveals EncodingWarning. Ref #685

    jaraco committed Jun 30, 2024
    Copy the full SHA
    8e4e1d6 View commit details
  2. Merge pull request #685 from PyWarnFixerRepos/unspecified-encoding

    Fix pylint warning `unspecified-encoding`
    jaraco authored Jun 30, 2024
    Copy the full SHA
    6c1f10e View commit details

Commits on Jul 10, 2024

  1. Copy the full SHA
    33c4896 View commit details

Commits on Jul 19, 2024

  1. "preserve" does not require preview any more (jaraco/skeleton#133)

    * "preserve" does not require preview any more
    * Update URL in ruff.toml comment
    
    ---------
    
    Co-authored-by: Bartosz Sławecki <bartoszpiotrslawecki@gmail.com>
    DimitriPapadopoulos and Bartosz Sławecki authored Jul 19, 2024
    Copy the full SHA
    f087fb4 View commit details
  2. Copy the full SHA
    30f940e View commit details
  3. Merge https://github.com/jaraco/skeleton

    jaraco committed Jul 19, 2024
    Copy the full SHA
    a50407d View commit details
  4. Copy the full SHA
    ab34814 View commit details
  5. Merge https://github.com/jaraco/skeleton

    jaraco committed Jul 19, 2024
    Copy the full SHA
    b1b6094 View commit details

Commits on Aug 1, 2024

  1. Copy the full SHA
    a13a477 View commit details
  2. Copy the full SHA
    1877402 View commit details
  3. When constructing KeyringBackend subclasses, wrap set_password to enf…

    …orce non-empty usernames.
    jaraco committed Aug 1, 2024
    Copy the full SHA
    53ca9cc View commit details
  4. Add news fragment.

    jaraco committed Aug 1, 2024
    Copy the full SHA
    8b3fb17 View commit details

Commits on Aug 2, 2024

  1. Merge pull request #687 from jaraco/668-empty-user

    Deprecate empty usernames
    jaraco authored Aug 2, 2024
    Copy the full SHA
    2d484ee View commit details
  2. Finalize

    jaraco committed Aug 2, 2024
    Copy the full SHA
    30eecb9 View commit details
Showing with 72 additions and 13 deletions.
  1. +1 −1 .readthedocs.yaml
  2. +9 −0 NEWS.rst
  3. +36 −2 keyring/backend.py
  4. +8 −1 keyring/core.py
  5. +6 −0 keyring/testing/backend.py
  6. +5 −4 pyproject.toml
  7. +4 −2 ruff.toml
  8. +3 −3 tox.ini
2 changes: 1 addition & 1 deletion .readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ python:
install:
- path: .
extra_requirements:
- docs
- doc

# required boilerplate readthedocs/readthedocs.org#10401
build:
9 changes: 9 additions & 0 deletions NEWS.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
v25.3.0
=======

Features
--------

- Deprecated support for empty usernames. Now all backends will reject an empty string as input for the 'username' field when setting a password. Later this deprecation will become a more visible user warning and even later an error. If this warning is triggered in your environment, please consider using a static value (even 'username') or comment in the issue and describe the use-case that demands support for empty usernames. (#668)


v25.2.1
=======

38 changes: 36 additions & 2 deletions keyring/backend.py
Original file line number Diff line number Diff line change
@@ -6,10 +6,12 @@

import abc
import copy
import functools
import logging
import operator
import os
import typing
import warnings

from jaraco.context import ExceptionTrap
from jaraco.functools import once
@@ -27,18 +29,38 @@

class KeyringBackendMeta(abc.ABCMeta):
"""
A metaclass that's both an ABCMeta and a type that keeps a registry of
all (non-abstract) types.
Specialized subclass behavior.
Keeps a registry of all (non-abstract) types.
Wraps set_password to validate the username.
"""

def __init__(cls, name, bases, dict):
super().__init__(name, bases, dict)
cls._register()
cls._validate_username_in_set_password()

def _register(cls):
if not hasattr(cls, '_classes'):
cls._classes = set()
classes = cls._classes
if not cls.__abstractmethods__:
classes.add(cls)

def _validate_username_in_set_password(cls):
"""
Wrap ``set_password`` such to validate the passed username.
"""
orig = cls.set_password

@functools.wraps(orig)
def wrapper(self, system, username, *args, **kwargs):
self._validate_username(username)
return orig(self, system, username, *args, **kwargs)

cls.set_password = wrapper


class KeyringBackend(metaclass=KeyringBackendMeta):
"""The abstract base class of the keyring, every backend must implement
@@ -103,6 +125,18 @@ def get_password(self, service: str, username: str) -> str | None:
"""Get password of the username for the service"""
return None

def _validate_username(self, username: str) -> None:
"""
Ensure the username is not empty.
"""
if not username:
warnings.warn(
"Empty usernames are deprecated. See #668",
DeprecationWarning,
stacklevel=3,
)
# raise ValueError("Username cannot be empty")

@abc.abstractmethod
def set_password(self, service: str, username: str, password: str) -> None:
"""Set password for the username of the service.
9 changes: 8 additions & 1 deletion keyring/core.py
Original file line number Diff line number Diff line change
@@ -37,6 +37,13 @@ def get_keyring() -> backend.KeyringBackend:
def disable() -> None:
"""
Configure the null keyring as the default.
>>> fs = getfixture('fs')
>>> disable()
>>> disable()
Traceback (most recent call last):
...
RuntimeError: Refusing to overwrite...
"""
root = platform.config_root()
try:
@@ -47,7 +54,7 @@ def disable() -> None:
if os.path.exists(filename):
msg = f"Refusing to overwrite {filename}"
raise RuntimeError(msg)
with open(filename, 'w') as file:
with open(filename, 'w', encoding='utf-8') as file:
file.write('[backend]\ndefault-keyring=keyring.backends.null.Keyring')


6 changes: 6 additions & 0 deletions keyring/testing/backend.py
Original file line number Diff line number Diff line change
@@ -163,6 +163,12 @@ def test_credential(self):
('user2', 'password2'),
)

@pytest.mark.xfail("platform.system() == 'Windows'", reason="#668")
def test_empty_username(self):
with pytest.deprecated_call():
self.set_password('service1', '', 'password1')
assert self.keyring.get_password('service1', '') == 'password1'

def test_set_properties(self, monkeypatch):
env = dict(KEYRING_PROPERTY_FOO_BAR='fizz buzz', OTHER_SETTING='ignore me')
monkeypatch.setattr(os, 'environ', env)
9 changes: 5 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -33,21 +33,22 @@ dependencies = [
dynamic = ["version"]

[project.urls]
Homepage = "https://github.com/jaraco/keyring"
Source = "https://github.com/jaraco/keyring"

[project.optional-dependencies]
testing = [
test = [
# upstream
"pytest >= 6, != 8.1.*",
"pytest-checkdocs >= 2.4",
"pytest-cov",
"pytest-mypy",
"pytest-enabler >= 2.2",
"pytest-ruff >= 0.2.1",
"pytest-ruff >= 0.2.1; sys_platform != 'cygwin'",

# local
"pyfakefs",
]
docs = [
doc = [
# upstream
"sphinx >= 3.5",
"jaraco.packaging >= 9.3",
6 changes: 4 additions & 2 deletions ruff.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[lint]
extend-select = [
"C901",
"PERF401",
"W",
]
ignore = [
@@ -22,7 +23,8 @@ ignore = [
]

[format]
# Enable preview, required for quote-style = "preserve"
# Enable preview to get hugged parenthesis unwrapping and other nice surprises
# See https://github.com/jaraco/skeleton/pull/133#issuecomment-2239538373
preview = true
# https://docs.astral.sh/ruff/settings/#format-quote-style
# https://docs.astral.sh/ruff/settings/#format_quote-style
quote-style = "preserve"
6 changes: 3 additions & 3 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@ commands =
pytest {posargs}
usedevelop = True
extras =
testing
test

[testenv:diffcov]
description = run tests and check that diff from main is covered
@@ -22,8 +22,8 @@ commands =
[testenv:docs]
description = build the documentation
extras =
docs
testing
doc
test
changedir = docs
commands =
python -m sphinx -W --keep-going . {toxinidir}/build/html