<commit_before>#  Copyright 2008 Nokia Siemens Networks Oyj
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.


# TODO: assertions, checks, generate html and check, write internal tests
# TODO: `` comments
# TODO: Check documentation and use short docs. Is some more examples needed?
import re
import string as STRING
try:
    from random import sample
except ImportError:   # No random.sample in Jython 2.2
    from random import randint
    def sample(chars, length):
        max_index = len(chars) - 1
        return [ chars[randint(0, max_index)] for i in xrange(length) ]

from robot import utils


class String:
    
    """A test library for string manipulation and verification.

    `String` is Robot Framework's standard library for manipulating
    strings (e.g. `Replace String With Regexp`, `Split To Lines`) and
    verifying their contents (e.g. `Should Be String`).

    Following keywords from the BuiltIn library can also be used with
    strings:
    - `Catenate`
    - `Get Length`
    - `Length Should Be`
    - `Should (Not) Match (Regexp)`
    - `Should (Not) Be Empty`
    - `Should (Not) Be Equal (As Strings)`
    - `Should (Not) Contain`
    - `Should (Not) Start With`
    - `Should (Not) End With`
    """

    ROBOT_LIBRARY_SCOPE = 'GLOBAL'
    ROBOT_LIBRARY_VERSION = utils.get_version()

    def get_line_count(self, string):
        """Returns the number of lines."""
        return len(string.splitlines())

    def split_to_lines(self, string, start=0, end=None):
        """Converts `string` to list of lines. 
        
        Ends of lines are removed. It is possible to get only selection of 
        lines, from `start` to `end`. Line numbering starts from 0. 

        Example:
        | @{lines} = | Split to lines | ${manylines} |
        | @{first two lines} = | Split to lines | ${manylines} | 0 | 1 |
        """
        lines = string.splitlines()
        start = self._convert_to_int(start, 'start')
        if not lines:
            return []
        if not end:
            return lines[start:]
        end = self._convert_to_int(end, 'end')
        return lines[start:end]

    def replace_string(self, string, search_for, replace_with, count=0):
        """ Replaces `search_for` in `string` with `replace_with`.

        You can specify how many occurrences are replaced with `count`,
        otherwise all occurrences are replaced.
        """        
        count = self._convert_to_int(count, 'count')
        if count <= 0:
            return string.replace(search_for, replace_with)
        return string.replace(search_for, replace_with, count)

    def replace_string_with_regexp(self, string, pattern, replace_with, count=0):
        """Replaces matches with `pattern` in `string` with `replace_with`.

        You can specify how many `pattern` occurrences are replaced with `count`,
        otherwise all occurrences are replaced.<commit_msg>Get Lines Matching (issue 285)<commit_after>#  Copyright 2008 Nokia Siemens Networks Oyj
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.


# TODO: assertions, checks, generate html and check, write internal tests
# TODO: `` comments
# TODO: Check documentation and use short docs. Is some more examples needed?
import re
from fnmatch import fnmatchcase
import string as STRING
try:
    from random import sample
except ImportError:   # No random.sample in Jython 2.2
    from random import randint
    def sample(chars, length):
        max_index = len(chars) - 1
        return [ chars[randint(0, max_index)] for i in xrange(length) ]

from robot import utils


class String:
    
    """A test library for string manipulation and verification.

    `String` is Robot Framework's standard library for manipulating
    strings (e.g. `Replace String With Regexp`, `Split To Lines`) and
    verifying their contents (e.g. `Should Be String`).

    Following keywords from the BuiltIn library can also be used with
    strings:
    - `Catenate`
    - `Get Length`
    - `Length Should Be`
    - `Should (Not) Match (Regexp)`
    - `Should (Not) Be Empty`
    - `Should (Not) Be Equal (As Strings)`
    - `Should (Not) Contain`
    - `Should (Not) Start With`
    - `Should (Not) End With`
    """

    ROBOT_LIBRARY_SCOPE = 'GLOBAL'
    ROBOT_LIBRARY_VERSION = utils.get_version()

    def get_line_count(self, string):
        """Returns the number of lines."""
        return len(string.splitlines())

    def split_to_lines(self, string, start=0, end=None):
        """Converts `string` to list of lines. 
        
        Ends of lines are removed. It is possible to get only selection of 
        lines, from `start` to `end`. Line numbering starts from 0. 

        Example:
        | @{lines} = | Split to lines | ${manylines} |
        | @{first two lines} = | Split to lines | ${manylines} | 0 | 1 |
        """
        lines = string.splitlines()
        start = self._convert_to_int(start, 'start')
        if not lines:
            return []
        if not end:
            return lines[start:]
        end = self._convert_to_int(end, 'end')
        return lines[start:end]

    def get_lines_containing_string(self, string, pattern, case_insensitive=False):
        if case_insensitive:
            pattern = pattern.lower()
            contains = lambda line: pattern in line.lower()
        else:
            contains = lambda line: pattern in line
        return self._get_matching_lines(string, contains)

    def get_lines_matching_pattern(self, string, pattern, case_insensitive=False):
        if case_insensitive:
            pattern = pattern.lower()
            matches = lambda line: fnmatchcase(line.lower(), pattern)
        else:
            matches = lambda line: fnmatchcase(line, pattern)
        return self._get_matching_lines(string, matches)

    def get_lines_matching_regexp(self, string, pattern):
        regexp = re.compile('^%s$' % pattern)
        return self._get_matching_lines(string, regexp.match)

    def _get_matching_lines(self, string, matches):
        lines = string.splitlines()
        matching = [ line for line in lines if matches(line) ]
        print '*INFO* %d out of %d lines matched' % (len(matching), len(lines))
        return '\n'.join(matching)
    
    def replace_string(self, string, search_for, replace_with, count=0):
        """ Replaces `search_for` in `string` with `replace_with`.

        You can specify how many occurrences are replaced with `count`,
        otherwise all occurrences are replaced.
        """        
        count = self._convert_to_int(count, 'count')
        if count <= 0:
            return string.replace(search_for, replace_with)
        return string.replace(search_for, replace_with, count)

    def replace_string_with_regexp(self, string, pattern, replace_with, count=0):
        """Replaces matches with `pattern` in `string` with `replace_with`.

        You can specify how many `pattern` occurrences are replaced with `count`,
        otherwise all occurrences are replaced.
{'fraction_non_alphanumeric': 0.09251156394549319, 'fraction_numerical': 0.005125640705088136, 'mean_word_length': 2.838771593090211, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '1183629', 'n_tokens_mistral': 2324, 'n_tokens_neox': 2209, 'n_words': 847}