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

Add python 3.12 support and remove python xdg #401

Merged
merged 2 commits into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions podman/api/path_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""Helper functions for managing paths"""

import errno
import getpass
import os
import stat


def get_runtime_dir() -> str:
"""Returns the runtime directory for the current user"""
try:
return os.environ['XDG_RUNTIME_DIR']
except KeyError:
user = getpass.getuser()
fallback = f'/tmp/podmanpy-runtime-dir-fallback-{user}'

try:
# This must be a real directory, not a symlink, so attackers can't
# point it elsewhere. So we use lstat to check it.
fallback_st = os.lstat(fallback)
except OSError as e:
if e.errno == errno.ENOENT:
os.mkdir(fallback, 0o700)
else:
raise
else:
# The fallback must be a directory
if not stat.S_ISDIR(fallback_st.st_mode):
os.unlink(fallback)
os.mkdir(fallback, 0o700)
# Must be owned by the user and not accessible by anyone else
elif (fallback_st.st_uid != os.getuid()) or (
fallback_st.st_mode & (stat.S_IRWXG | stat.S_IRWXO)
):
os.rmdir(fallback)
os.mkdir(fallback, 0o700)

return fallback


def get_xdg_config_home() -> str:
"""Returns the XDG_CONFIG_HOME directory for the current user"""
try:
return os.environ["XDG_CONFIG_HOME"]
except KeyError:
return os.path.join(os.path.expanduser("~"), ".config")
4 changes: 2 additions & 2 deletions podman/api/ssh.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
from typing import Optional, Union

import time
import xdg.BaseDirectory

import urllib3
import urllib3.connection

from requests.adapters import DEFAULT_POOLBLOCK, DEFAULT_RETRIES, HTTPAdapter
from podman.api.path_utils import get_runtime_dir

from .adapter_utils import _key_normalizer

Expand All @@ -46,7 +46,7 @@ def __init__(self, uri: str, identity: Optional[str] = None):
self.identity = identity
self._proc: Optional[subprocess.Popen] = None

runtime_dir = pathlib.Path(xdg.BaseDirectory.get_runtime_dir(strict=False)) / "podman"
runtime_dir = pathlib.Path(get_runtime_dir()) / "podman"
runtime_dir.mkdir(mode=0o700, parents=True, exist_ok=True)

self.local_sock = runtime_dir / f"podman-forward-{random.getrandbits(80):x}.sock"
Expand Down
7 changes: 2 additions & 5 deletions podman/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@
from pathlib import Path
from typing import Any, Dict, Optional

import xdg.BaseDirectory

from podman.api import cached_property
from podman.api.client import APIClient
from podman.api.path_utils import get_runtime_dir
from podman.domain.config import PodmanConfig
from podman.domain.containers_manager import ContainersManager
from podman.domain.events import EventsManager
Expand Down Expand Up @@ -70,9 +69,7 @@ def __init__(self, **kwargs) -> None:
# Override configured identity, if provided in arguments
api_kwargs["identity"] = kwargs.get("identity", str(connection.identity))
elif "base_url" not in api_kwargs:
path = str(
Path(xdg.BaseDirectory.get_runtime_dir(strict=False)) / "podman" / "podman.sock"
)
path = str(Path(get_runtime_dir()) / "podman" / "podman.sock")
api_kwargs["base_url"] = "http+unix://" + path
self.api = APIClient(**api_kwargs)

Expand Down
5 changes: 2 additions & 3 deletions podman/domain/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
from typing import Dict, Optional
import json

import xdg.BaseDirectory

from podman.api import cached_property
from podman.api.path_utils import get_xdg_config_home

if sys.version_info >= (3, 11):
from tomllib import loads as toml_loads
Expand Down Expand Up @@ -69,7 +68,7 @@ def __init__(self, path: Optional[str] = None):

self.is_default = False
if path is None:
home = Path(xdg.BaseDirectory.xdg_config_home)
home = Path(get_xdg_config_home())
self.path = home / "containers" / "podman-connections.json"
old_toml_file = home / "containers" / "containers.conf"
self.is_default = True
Expand Down
12 changes: 4 additions & 8 deletions podman/tests/unit/test_podmanclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
from unittest.mock import MagicMock

import requests_mock
import xdg

from podman import PodmanClient, tests
from podman.api.path_utils import get_runtime_dir, get_xdg_config_home


class PodmanClientTestCase(unittest.TestCase):
Expand Down Expand Up @@ -88,7 +88,7 @@ def test_connect(self):
)

# Build path to support tests running as root or a user
expected = Path(xdg.BaseDirectory.xdg_config_home) / "containers" / "containers.conf"
expected = Path(get_xdg_config_home()) / "containers" / "containers.conf"
PodmanClientTestCase.opener.assert_called_with(expected, encoding="utf-8")

def test_connect_404(self):
Expand All @@ -100,16 +100,12 @@ def test_connect_default(self):
with mock.patch.multiple(Path, open=self.mocked_open, exists=MagicMock(return_value=True)):
with PodmanClient() as client:
expected = "http+unix://" + urllib.parse.quote_plus(
str(
Path(xdg.BaseDirectory.get_runtime_dir(strict=False))
/ "podman"
/ "podman.sock"
)
str(Path(get_runtime_dir()) / "podman" / "podman.sock")
)
self.assertEqual(client.api.base_url.geturl(), expected)

# Build path to support tests running as root or a user
expected = Path(xdg.BaseDirectory.xdg_config_home) / "containers" / "containers.conf"
expected = Path(get_xdg_config_home()) / "containers" / "containers.conf"
PodmanClientTestCase.opener.assert_called_with(expected, encoding="utf-8")


Expand Down
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# Any changes should be copied into pyproject.toml
pyxdg>=0.26
requests>=2.24
setuptools
sphinx
Expand Down
1 change: 0 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ python_requires = >=3.6
test_suite =
# Any changes should be copied into pyproject.toml
install_requires =
pyxdg >=0.26
requests >=2.24
tomli>=1.2.3; python_version<'3.11'
urllib3
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tox]
minversion = 3.2.0
envlist = pylint,coverage,py36,py38,py39,py310,py311
envlist = pylint,coverage,py36,py38,py39,py310,py311,py312
ignore_basepython_conflict = true

[testenv]
Expand Down
Loading