|
@@ -34,7 +34,6 @@ import pickle
|
|
|
import posixpath
|
|
import posixpath
|
|
|
import shlex
|
|
import shlex
|
|
|
import subprocess
|
|
import subprocess
|
|
|
-import sys
|
|
|
|
|
import threading
|
|
import threading
|
|
|
import time
|
|
import time
|
|
|
from contextlib import contextmanager
|
|
from contextlib import contextmanager
|
|
@@ -47,12 +46,9 @@ from tempfile import NamedTemporaryFile, TemporaryDirectory
|
|
|
|
|
|
|
|
import vobject
|
|
import vobject
|
|
|
|
|
|
|
|
|
|
+from radicale import xmlutils
|
|
|
from radicale.log import logger
|
|
from radicale.log import logger
|
|
|
|
|
|
|
|
-if sys.version_info >= (3, 5):
|
|
|
|
|
- # HACK: Avoid import cycle for Python < 3.5
|
|
|
|
|
- from radicale import xmlutils
|
|
|
|
|
-
|
|
|
|
|
if os.name == "nt":
|
|
if os.name == "nt":
|
|
|
import ctypes
|
|
import ctypes
|
|
|
import ctypes.wintypes
|
|
import ctypes.wintypes
|
|
@@ -97,10 +93,6 @@ INTERNAL_TYPES = ("multifilesystem",)
|
|
|
|
|
|
|
|
def load(configuration):
|
|
def load(configuration):
|
|
|
"""Load the storage manager chosen in configuration."""
|
|
"""Load the storage manager chosen in configuration."""
|
|
|
- if sys.version_info < (3, 5):
|
|
|
|
|
- # HACK: Avoid import cycle for Python < 3.5
|
|
|
|
|
- global xmlutils
|
|
|
|
|
- from radicale import xmlutils
|
|
|
|
|
storage_type = configuration.get("storage", "type")
|
|
storage_type = configuration.get("storage", "type")
|
|
|
if storage_type == "multifilesystem":
|
|
if storage_type == "multifilesystem":
|
|
|
collection_class = Collection
|
|
collection_class = Collection
|
|
@@ -241,27 +233,6 @@ def find_available_name(exists_fn, suffix=""):
|
|
|
raise RuntimeError("No unique random sequence found")
|
|
raise RuntimeError("No unique random sequence found")
|
|
|
|
|
|
|
|
|
|
|
|
|
-def scandir(path, only_dirs=False, only_files=False):
|
|
|
|
|
- """Iterator for directory elements. (For compatibility with Python < 3.5)
|
|
|
|
|
-
|
|
|
|
|
- ``only_dirs`` only return directories
|
|
|
|
|
-
|
|
|
|
|
- ``only_files`` only return files
|
|
|
|
|
-
|
|
|
|
|
- """
|
|
|
|
|
- if sys.version_info >= (3, 5):
|
|
|
|
|
- for entry in os.scandir(path):
|
|
|
|
|
- if ((not only_files or entry.is_file()) and
|
|
|
|
|
- (not only_dirs or entry.is_dir())):
|
|
|
|
|
- yield entry.name
|
|
|
|
|
- else:
|
|
|
|
|
- for name in os.listdir(path):
|
|
|
|
|
- p = os.path.join(path, name)
|
|
|
|
|
- if ((not only_files or os.path.isfile(p)) and
|
|
|
|
|
- (not only_dirs or os.path.isdir(p))):
|
|
|
|
|
- yield name
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
def get_etag(text):
|
|
def get_etag(text):
|
|
|
"""Etag from collection or item.
|
|
"""Etag from collection or item.
|
|
|
|
|
|
|
@@ -354,7 +325,8 @@ def path_to_filesystem(root, *paths):
|
|
|
# Check for conflicting files (e.g. case-insensitive file systems
|
|
# Check for conflicting files (e.g. case-insensitive file systems
|
|
|
# or short names on Windows file systems)
|
|
# or short names on Windows file systems)
|
|
|
if (os.path.lexists(safe_path) and
|
|
if (os.path.lexists(safe_path) and
|
|
|
- part not in scandir(safe_path_parent)):
|
|
|
|
|
|
|
+ part not in (e.name for e in
|
|
|
|
|
+ os.scandir(safe_path_parent))):
|
|
|
raise CollidingPathError(part)
|
|
raise CollidingPathError(part)
|
|
|
return safe_path
|
|
return safe_path
|
|
|
|
|
|
|
@@ -899,7 +871,10 @@ class Collection(BaseCollection):
|
|
|
with child_context_manager(sane_path, href):
|
|
with child_context_manager(sane_path, href):
|
|
|
yield collection.get(href)
|
|
yield collection.get(href)
|
|
|
|
|
|
|
|
- for href in scandir(filesystem_path, only_dirs=True):
|
|
|
|
|
|
|
+ for entry in os.scandir(filesystem_path):
|
|
|
|
|
+ if not entry.is_dir():
|
|
|
|
|
+ continue
|
|
|
|
|
+ href = entry.name
|
|
|
if not is_safe_filesystem_path_component(href):
|
|
if not is_safe_filesystem_path_component(href):
|
|
|
if not href.startswith(".Radicale"):
|
|
if not href.startswith(".Radicale"):
|
|
|
logger.debug("Skipping collection %r in %r",
|
|
logger.debug("Skipping collection %r in %r",
|
|
@@ -1174,7 +1149,8 @@ class Collection(BaseCollection):
|
|
|
history_folder = os.path.join(self._filesystem_path,
|
|
history_folder = os.path.join(self._filesystem_path,
|
|
|
".Radicale.cache", "history")
|
|
".Radicale.cache", "history")
|
|
|
try:
|
|
try:
|
|
|
- for href in scandir(history_folder):
|
|
|
|
|
|
|
+ for entry in os.scandir(history_folder):
|
|
|
|
|
+ href = entry.name
|
|
|
if not is_safe_filesystem_path_component(href):
|
|
if not is_safe_filesystem_path_component(href):
|
|
|
continue
|
|
continue
|
|
|
if os.path.isfile(os.path.join(self._filesystem_path, href)):
|
|
if os.path.isfile(os.path.join(self._filesystem_path, href)):
|
|
@@ -1285,7 +1261,10 @@ class Collection(BaseCollection):
|
|
|
return token, changes
|
|
return token, changes
|
|
|
|
|
|
|
|
def list(self):
|
|
def list(self):
|
|
|
- for href in scandir(self._filesystem_path, only_files=True):
|
|
|
|
|
|
|
+ for entry in os.scandir(self._filesystem_path):
|
|
|
|
|
+ if not entry.is_file():
|
|
|
|
|
+ continue
|
|
|
|
|
+ href = entry.name
|
|
|
if not is_safe_filesystem_path_component(href):
|
|
if not is_safe_filesystem_path_component(href):
|
|
|
if not href.startswith(".Radicale"):
|
|
if not href.startswith(".Radicale"):
|
|
|
logger.debug("Skipping item %r in %r", href, self.path)
|
|
logger.debug("Skipping item %r in %r", href, self.path)
|
|
@@ -1357,8 +1336,8 @@ class Collection(BaseCollection):
|
|
|
cache_folder = os.path.join(self._filesystem_path, ".Radicale.cache",
|
|
cache_folder = os.path.join(self._filesystem_path, ".Radicale.cache",
|
|
|
"item")
|
|
"item")
|
|
|
self._clean_cache(cache_folder, (
|
|
self._clean_cache(cache_folder, (
|
|
|
- href for href in scandir(cache_folder) if not
|
|
|
|
|
- os.path.isfile(os.path.join(self._filesystem_path, href))))
|
|
|
|
|
|
|
+ e.name for e in os.scandir(cache_folder) if not
|
|
|
|
|
+ os.path.isfile(os.path.join(self._filesystem_path, e.name))))
|
|
|
|
|
|
|
|
def _get_with_metadata(self, href, verify_href=True):
|
|
def _get_with_metadata(self, href, verify_href=True):
|
|
|
"""Like ``get`` but additonally returns the following metadata:
|
|
"""Like ``get`` but additonally returns the following metadata:
|