<commit_before># coding: utf-8
"""7z archive filesystems.
"""
from __future__ import absolute_import
from __future__ import unicode_literals

import collections
import io
import functools
import itertools
import stat

import six
import lzma
import py7zr
import iocursor
from py7zr.helpers import ArchiveTimestamp
from py7zr.py7zr import FILE_ATTRIBUTE_UNIX_EXTENSION

from ... import errors
from ...info import Info
from ...mode import Mode
from ...osfs import OSFS
from ...path import abspath, dirname, basename, join
from ...enums import ResourceType
from ...permissions import Permissions

from .. import base


class _Origin(object):
    def __init__(self, fs, path):
        self.fs = fs
        self.path = path
    def open(self, mode="rb"):
        return self.fs.openbin(self.path, mode)


class SevenZipReadFS(base.ArchiveReadFS):
    """A read-only filesystem within a 7z archive.
    """

    _meta = {
        'standard': {
            'case_insensitive': False,
            'network': False,
            'read_only': True,
            'supports_rename': False,
            'thread_safe': True,
            'unicode_paths': True,
            'virtual': False,
            'max_path_length': None,
            'max_sys_path_length': None,
            'invalid_path_chars': '\x00\x01',
        },
    }

    def __init__(self, handle, **options):  # noqa: D102, D107
        """Create a new 7z reader filesystem.

        Parameters:
            handle (`io.IOBase` or `str`): A filename or a readable
                file-like object storing the archive to read.

        Keyword Arguments:
            close_handle (`boolean`): If ``True``, close the handle
                when the filesystem is closed. **[default: True]**
            password (`str`): The password to use for decrypting the
                archive contents. **[default: None]**

        """
        super(SevenZipReadFS, self).__init__(handle, **options)
        self._password = options.get('password')
        self._start_position = self._handle.tell()

        _7z = None
        try:
            _7z = py7zr.SevenZipFile(handle, 'r', password=self._password)
        except py7zr.exceptions.PasswordRequired as exc:
            raise errors.CreateFailed(
                exc=errors.PermissionDenied(msg="7z archive is password protected", exc=exc)
            )
        except (lzma.LZMAError, TypeError) as exc:
            raise errors.CreateFailed(exc=exc)
        else:
            self._members = {abspath(info.filename):info for info in _7z.files}
            self._bydir = collections.defaultdict(list)
            for info in _7z.files:
                self._bydir[abspath(dirname(info.filename))].append(info)
        finally:
            if _7z is not None:
                _7z.close()

    def _get_info_from_entry(self, entry, namespaces=None):
        namespaces = namespaces or ()

        info = {
            'basic': {
                'name': basename(entry.filename),
                'is_dir': entry.is_directory,
            }
        }

        if "details" in namespaces:
            properties = entry.file_properties()
            info['details'] = details = {}
<commit_msg>Wrap `Bad7zFile` exceptions thrown when creating a `SevenZipReadFS`<commit_after># coding: utf-8
"""7z archive filesystems.
"""
from __future__ import absolute_import
from __future__ import unicode_literals

import collections
import io
import functools
import itertools
import stat

import six
import lzma
import py7zr
import iocursor
from py7zr.helpers import ArchiveTimestamp
from py7zr.py7zr import FILE_ATTRIBUTE_UNIX_EXTENSION
from py7zr.exceptions import Bad7zFile

from ... import errors
from ...info import Info
from ...mode import Mode
from ...osfs import OSFS
from ...path import abspath, dirname, basename, join
from ...enums import ResourceType
from ...permissions import Permissions

from .. import base


class _Origin(object):
    def __init__(self, fs, path):
        self.fs = fs
        self.path = path
    def open(self, mode="rb"):
        return self.fs.openbin(self.path, mode)


class SevenZipReadFS(base.ArchiveReadFS):
    """A read-only filesystem within a 7z archive.
    """

    _meta = {
        'standard': {
            'case_insensitive': False,
            'network': False,
            'read_only': True,
            'supports_rename': False,
            'thread_safe': True,
            'unicode_paths': True,
            'virtual': False,
            'max_path_length': None,
            'max_sys_path_length': None,
            'invalid_path_chars': '\x00\x01',
        },
    }

    def __init__(self, handle, **options):  # noqa: D102, D107
        """Create a new 7z reader filesystem.

        Parameters:
            handle (`io.IOBase` or `str`): A filename or a readable
                file-like object storing the archive to read.

        Keyword Arguments:
            close_handle (`boolean`): If ``True``, close the handle
                when the filesystem is closed. **[default: True]**
            password (`str`): The password to use for decrypting the
                archive contents. **[default: None]**

        """
        super(SevenZipReadFS, self).__init__(handle, **options)
        self._password = options.get('password')
        self._start_position = self._handle.tell()

        _7z = None
        try:
            _7z = py7zr.SevenZipFile(handle, 'r', password=self._password)
        except py7zr.exceptions.PasswordRequired as exc:
            raise errors.CreateFailed(
                exc=errors.PermissionDenied(msg="7z archive is password protected", exc=exc)
            )
        except (lzma.LZMAError, TypeError, Bad7zFile) as exc:
            raise errors.CreateFailed(exc=exc)
        else:
            self._members = {abspath(info.filename):info for info in _7z.files}
            self._bydir = collections.defaultdict(list)
            for info in _7z.files:
                self._bydir[abspath(dirname(info.filename))].append(info)
        finally:
            if _7z is not None:
                _7z.close()

    def _get_info_from_entry(self, entry, namespaces=None):
        namespaces = namespaces or ()

        info = {
            'basic': {
                'name': basename(entry.filename),
                'is_dir': entry.is_directory,
            }
        }

        if "details" in namespaces:
            properties = entry.file_properties()
            info['details'] = details = {}

{'fraction_non_alphanumeric': 0.10166872682323856, 'fraction_numerical': 0.00896168108776267, 'mean_word_length': 2.185531496062992, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4648399', 'n_tokens_mistral': 1919, 'n_tokens_neox': 1825, 'n_words': 520}