コード例 #1
0
    def test_total_size_calculated_correctly(self, tmp_folder):
        """Check if directory scanning calculates the item sizes correctly.
        Testing for: @property def total_size(self).

        :param tmp_folder: Test params and dummy test folder factory fixture pair.
        :type tmp_folder: (dict, dirtools.tests.factory.DummyFolderFactory)
        """
        params, factory = tmp_folder
        scan = Folder(factory.path, params['sort_by'], params['level'])
        items_len = len(list(scan.items()))

        # For an empty folder
        if factory.total_items == 0:
            assert factory._level == 0
            assert factory.total_size == 0
            assert scan.total_size == 0
            assert items_len == 0

        # Compare with the testing factory testing desired_size param
        assert scan.total_size == sum(
            [i['size'] for i in scan.items(humanise=False)])
        assert scan.total_size == factory.total_size
        assert items_len == factory.total_items

        # Because the factory class does not create at exact size
        assert scan.total_size == factory.total_size
        assert scan.total_size >= 0.9 * human2bytes(params['total_size'])
        assert scan.total_size <= 1.1 * human2bytes(params['total_size'])
コード例 #2
0
def test_human2bytes_raises_expected_errors():
    # Check TypeError(s)
    for invalid in (None, 123, 123.0, [1, 2, 3]):
        with pytest.raises(TypeError):
            utils.human2bytes(invalid)

    # Check ValueErrors(s)
    for invalid in ('123 bytes', '123 foo', '123 m'):
        with pytest.raises(ValueError):
            utils.human2bytes(invalid)
コード例 #3
0
ファイル: scanner.py プロジェクト: comfortablynick/dirtools3
    def cleanup_items(self,
                      max_total_size: str,
                      humanise: bool = True,
                      precision: int = 2) -> Iterator[dict]:
        """Completely remove every item starting from the first in given sorting order until it reaches to ``max_total_size`` parameter.

        Returns empty generator if the given ``max_total_size`` parameter is equal or greater than entire total size. Otherwise removes and yields every deleted item.

        Blocks until the scanning operation has been completed on first access.

        .. warning::

            Result of this method is to DELETE the physical files / folders
            on your disk until the given size matches the actual size
            and there is NO UNDO for this operation.

        :param max_total_size: Human representation of total desired size.
                See: :func:``dirtools.utils.human2bytes``.
        :type max_total_size: str
        :param humanise: Humanise flag (required, no default value).
        :type humanise: bool
        :param precision: The floating precision of the human-readable size format (defaults to 2).
        :type precision: int
        :return: iterator
        """
        self._await()

        # Start deleting in the sorted order
        old_len = self._items_len
        old_size = self._total_size
        max_total_size = utils.human2bytes(max_total_size)
        while self._total_size > max_total_size:
            item = self._items.popleft()
            self._total_size -= item["size"]
            self._items_len -= 1
            item_path = os.path.abspath(os.path.join(self._root, item["name"]))

            # REMOVE THE ITEM PERMANENTLY
            try:
                shutil.rmtree(item_path)
            except NotADirectoryError:
                os.remove(item_path)

            # yield removed item
            yield self._humanise_item(item, precision) if humanise else item

        # Reduced to desired size
        logger.debug(
            "{del_len:d} items with total of {del_size} data has been deleted."
            .format(
                del_len=old_len - self._items_len,
                del_size=utils.bytes2human(old_size - self._total_size),
            ))
コード例 #4
0
    def test_invoke_trimming_down_instead_of_listing(self, monkeypatch,
                                                     tmp_folder,
                                                     clone_factory):
        """
        :param monkeypatch: pytest monkey patch fixture
        :type monkeypatch: _pytest.monkeypatch.MonkeyPatch
        :param tmp_folder: Test params and dummy test folder factory fixture pair.
        :type tmp_folder: (dict, dirtools.tests.factory.DummyFolderFactory)
        :param clone_factory: Factory to create `Folder` clone instance.
        :type clone_factory: dirtools.tests.conftest.clone_factory._factory
        :return:
        """
        params, _factory = tmp_folder
        if params['total_items'] == 0:
            return

        trim_down = int(human2bytes(params['total_size']) / 2)
        trim_down_human = bytes2human(trim_down)
        # Use another factory folder that is not shared with other tests
        with DummyFolderFactory(params['total_items'],
                                params['total_size'],
                                level=params['level']) as factory:
            # Create a scanner mock from the factory
            scan = clone_factory(factory.path,
                                 params['sort_by'],
                                 level=params['level'])
            FolderScanMock = Mock(return_value=scan)
            monkeypatch.setattr(self.dirt, 'Folder', FolderScanMock)

            # Give only numeric trim-down value that shouldn't be accepted
            result = self.runner.invoke(self.dirt.invoke_dirtools3, [
                factory.path, '-s',
                str(params['sort_by']).lower(), '--trim-down',
                str(trim_down)
            ])
            assert result.exception is None
            assert '--trim-down value cannot be only numeric' in result.output

            result = self.runner.invoke(self.dirt.invoke_dirtools3, [
                factory.path, '-s',
                str(params['sort_by']).lower(), '--trim-down', trim_down_human
            ])
            assert result.exception is None
            scan.items.assert_not_called()
            scan.cleanup_items.assert_called_once_with(
                trim_down_human,
                humanise=not self._DEFAULTS['nohuman'],
                precision=self._DEFAULTS['precision'])
コード例 #5
0
ファイル: factory.py プロジェクト: comfortablynick/dirtools3
    def __init__(self, total_items, total_size, **kwargs):
        # Pick a random folder name
        # under OS dependent temporary space if no "_root" keyword is given
        self._root = '{root}/dirtools3-{rand}'.format(
            root=kwargs.get('_root', tempfile.gettempdir()),
            rand=self._gen_rand_str(3))

        # Save configs
        self.total_items = int(total_items)
        self._desired_size = utils.human2bytes(total_size)
        self._level = int(kwargs.get('level', self._level))
        assert self._level <= (self.total_items // 4), \
            'Level cannot be more than a 4rd of total_items: {0:d}'.format(self.total_items)
        self._max_depth = int(kwargs.get('max_depth', self._max_depth))
        assert self._max_depth >= 0, 'Max depth cannot be negative.'
        self.cleanup = bool(kwargs.get('cleanup', self.cleanup))
コード例 #6
0
def test_bytes2human_calculates_correct_bytes_to_human():
    for byte_val, human in VALID_BYTES2HUMAN:
        # Also assert well-formatted human value to bytes
        assert byte_val == utils.human2bytes(human)
        assert utils.bytes2human(byte_val, precision=11) == human
コード例 #7
0
def test_human2bytes_calculates_correct_values_to_bytes():
    for human, byte_val in VALID_HUMAN2BYTES:
        assert utils.human2bytes(human) == byte_val