<commit_before>#!/usr/bin/env python
"""Dirge - Directory generator"""

from __future__ import absolute_import, division, unicode_literals, print_function

import re
from util.constants import constants


@constants
class Const(object):
    DIR_LINE_REGEX = re.compile(r"(\W*?)([-]+)?(\w[^|/\\?:<>]*)")


def parse_line(line):
    """Parses a single line of a directory specification.

    This function should search a line for a directory name, and then return that name and its indent length

    :param line: Line to parse
    :type line: str
    :return: A tuple containing the directory name and the level of the directory
    :rtype: tuple

    :Example:

    >>> parse_line(' | | +-directory') == ('directory', 6)
    True
    >>> parse_line('-root') == ('root', 0)
    True
    >>> parse_line('        deep-folder') == ('deep-folder', 8)
    True
    >>> parse_line('-----> folder') == ('folder', 7)
    True

    """

    # Parse the line with a regex
    m = Const.DIR_LINE_REGEX.match(line)

    if m:  # If the regex matched
        return m.group(3), len(m.group(1))  # Return the values
    else:  # Otherwise, no match
        return (None, 0)  # Return None


def create_full_path(path_stack, name, depth):
    """Creates a full path from the name, level and current stack.

    Walks back up path_stack until a lower level path is found. A fully
    qualified path is returned. The stack is not modified, but the resulting
    value should be appended to the stack before the next invocation of this
    function.

    :param path_stack: A stack of directory paths and their 'level'
    :param name: The name of the directory to insert into the tree
    :param depth: The 'depth' or 'level' of the new directory
    :type path_stack: list
    :type name: str
    :type depth: int
    :return: Full path of new directory, or None if there are no parents
    :rtype: str, None

    :Example:

    >>> # Stack representing dirs a/b a/c/d
    >>> stack = [
    ...     ('a', 0),
    ...     ('a/b', 2),
    ...     ('a/c', 2),
    ...     ('a/c/d', 4),
    ... ]
    >>> create_full_path(stack, 'e', 6) == 'a/c/d/e'
    True
    >>> create_full_path(stack, 'f', 4) == 'a/c/f'
    True
    >>> create_full_path(stack, 'g', 2) == 'a/g'
    True
    >>> create_full_path(stack, 'h', 0) is None
    True

    """
    pass


def determine_paths(read, parent=None):
    """Determines the list of paths to create from a directory specification

    :param read: Text to parse for generation rules
    :param parent: Parent directory/prefix to append to each generated directory
    :type read: str, file
    :type parent: str
    :return: A list of paths that should be generated
    :rtype: list

    :Example with string:

    >>> text = '''
    ...
    ... -path
    ...   |
    ...   +-along
    ...   |  |
    ...   |  +-the<commit_msg>Changed create_full_path doctest to be os indep.<commit_after>#!/usr/bin/env python
"""Dirge - Directory generator"""

from __future__ import absolute_import, division, unicode_literals, print_function

import re

from os import path
from util.constants import constants


@constants
class Const(object):
    DIR_LINE_REGEX = re.compile(r"(\W*?)([-]+)?(\w[^|/\\?:<>]*)")


def parse_line(line):
    """Parses a single line of a directory specification.

    This function should search a line for a directory name, and then return that name and its indent length

    :param line: Line to parse
    :type line: str
    :return: A tuple containing the directory name and the level of the directory
    :rtype: tuple

    :Example:

    >>> parse_line(' | | +-directory') == ('directory', 6)
    True
    >>> parse_line('-root') == ('root', 0)
    True
    >>> parse_line('        deep-folder') == ('deep-folder', 8)
    True
    >>> parse_line('-----> folder') == ('folder', 7)
    True

    """

    # Parse the line with a regex
    m = Const.DIR_LINE_REGEX.match(line)

    if m:  # If the regex matched
        return m.group(3), len(m.group(1))  # Return the values
    else:  # Otherwise, no match
        return (None, 0)  # Return None


def create_full_path(path_stack, name, depth):
    """Creates a full path from the name, level and current stack.

    Walks back up path_stack until a lower level path is found. A fully
    qualified path is returned. The stack is not modified, but the resulting
    value should be appended to the stack before the next invocation of this
    function.

    :param path_stack: A stack of directory paths and their 'level'
    :param name: The name of the directory to insert into the tree
    :param depth: The 'depth' or 'level' of the new directory
    :type path_stack: list
    :type name: str
    :type depth: int
    :return: Full path of new directory, or None if there are no parents
    :rtype: str, None

    :Example:

    >>> from os import path
    >>> stack = [
    ...     (path.join('a'), 0),
    ...     (path.join('a', 'b'), 2),
    ...     (path.join('a', 'c'), 2),
    ...     (path.join('a', 'c', 'd'), 4),
    ... ]
    >>> create_full_path(stack, 'e', 6) == path.join('a', 'c', 'd', 'e')
    True
    >>> create_full_path(stack, 'f', 4) == path.join('a', 'c', 'f')
    True
    >>> create_full_path(stack, 'g', 2) == path.join('a', 'g')
    True
    >>> create_full_path(stack, 'h', 0) is None
    True

    """
    pass


def determine_paths(read, parent=None):
    """Determines the list of paths to create from a directory specification

    :param read: Text to parse for generation rules
    :param parent: Parent directory/prefix to append to each generated directory
    :type read: str, file
    :type parent: str
    :return: A list of paths that should be generated
    :rtype: list

    :Example with string:

    >>> text = '''
    ...
    ... -path
    ...   |
    ...   +-along
    ...   |  |
    ...   |  +-the
{'fraction_non_alphanumeric': 0.13725825774430944, 'fraction_numerical': 0.005134348793428034, 'mean_word_length': 2.5963076923076924, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 73, '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': '689167', 'n_tokens_mistral': 1874, 'n_tokens_neox': 1786, 'n_words': 676}