Skip to content

Commit

Permalink
With 2.7 dropped, use shutil disk_usage function universally.
Browse files Browse the repository at this point in the history
  • Loading branch information
rtibbles committed Mar 30, 2024
1 parent bac2ab5 commit 70fb3a1
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 65 deletions.
36 changes: 11 additions & 25 deletions kolibri/core/device/test/test_api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import os
import platform
import sys
import uuid
from collections import namedtuple
from datetime import timedelta
Expand Down Expand Up @@ -375,30 +374,17 @@ def setUp(self):
facility=self.facility,
)

def test_posix_freespace(self):
if not sys.platform.startswith("win"):
with mock.patch("kolibri.utils.system.os.statvfs") as os_statvfs_mock:
statvfs_result = namedtuple("statvfs_result", ["f_frsize", "f_bavail"])
os_statvfs_mock.return_value = statvfs_result(f_frsize=1, f_bavail=2)

response = self.client.get(
reverse("kolibri:core:freespace"), {"path": "test"}
)

os_statvfs_mock.assert_called_with(os.path.realpath("test"))
self.assertEqual(response.data, {"freespace": 2})

def test_win_freespace_fail(self):
if sys.platform.startswith("win"):
ctypes_mock = mock.MagicMock()
with mock.patch.dict("sys.modules", ctypes=ctypes_mock):
ctypes_mock.windll.kernel32.GetDiskFreeSpaceExW.return_value = 0
ctypes_mock.winError.side_effect = OSError
try:
self.client.get(reverse("kolibri:core:freespace"), {"path": "test"})
except OSError:
# check if ctypes.winError() has been called
ctypes_mock.winError.assert_called_with()
def test_freespace(self):
with mock.patch("kolibri.utils.system.shutil.disk_usage") as diskusage_mock:
diskusage_result = namedtuple("diskusage_result", ["free"])
diskusage_mock.return_value = diskusage_result(free=2)

response = self.client.get(
reverse("kolibri:core:freespace"), {"path": "test"}
)

diskusage_mock.assert_called_with(os.path.realpath("test"))
self.assertEqual(response.data, {"freespace": 2})


class DeviceInfoTestCase(APITestCase):
Expand Down
2 changes: 1 addition & 1 deletion kolibri/core/discovery/utils/filesystem/posix.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
def get_drive_list():
"""
Gets a list of drives and metadata by parsing the output of `mount`, and adding additional info from various commands.
Disk size/usage comes from shutil.disk_usage or os.statvfs, and name/type info from dbus (Linux) or diskutil (OSX).
Disk size/usage comes from shutil.disk_usage, and name/type info from dbus (Linux) or diskutil (OSX).
"""

if sys.platform == "darwin":
Expand Down
47 changes: 8 additions & 39 deletions kolibri/utils/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
"""
import logging
import os
import shutil
import sys

from django.db import connections

from .conf import KOLIBRI_HOME
from .conf import OPTIONS
from kolibri.utils.android import on_android

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -127,44 +127,13 @@ def write(self, s):

def get_free_space(path=KOLIBRI_HOME):

while path and not os.path.exists(path):
path = os.path.dirname(path) # look to parent if it doesn't exist
if not path:
raise Exception("Could not calculate free space")

if sys.platform.startswith("win"):
import ctypes

free = ctypes.c_ulonglong(0)
check = ctypes.windll.kernel32.GetDiskFreeSpaceExW(
ctypes.c_wchar_p(path), None, None, ctypes.pointer(free)
)
if check == 0:
raise ctypes.winError()
result = free.value
elif on_android():
# This is meant for android, which needs to interact with android API to understand free
# space. If we're somehow getting here on non-android, we've got a problem.
try:
from jnius import autoclass

StatFs = autoclass("android.os.StatFs")
AndroidString = autoclass("java.lang.String")

st = StatFs(AndroidString(path))

try:
# for api version 18+
result = st.getFreeBlocksLong() * st.getBlockSizeLong()
except Exception:
# for api versions < 18
result = st.getFreeBlocks() * st.getBlockSize()

except Exception as e:
raise e
else:
st = os.statvfs(os.path.realpath(path))
result = st.f_bavail * st.f_frsize
path = os.path.realpath(path)

while path and not os.path.exists(path) and not os.path.isdir(path):
path = os.path.dirname(
path
) # look to parent if it doesn't exist or isn't a directory
result = shutil.disk_usage(path).free

return max(result - OPTIONS["Deployment"]["MINIMUM_DISK_SPACE"], 0)

Expand Down

0 comments on commit 70fb3a1

Please sign in to comment.