import collections

import pyconll._parser
from pyconll.unit import Sentence


class Conll:
    """
    The abstraction for a CoNLL-U file. A CoNLL-U file is more or less just a
    collection of sentences in order. These sentences can be accessed by
    sentence id or by numeric index. Note that sentences must be separated by
    whitespace. CoNLL-U also specifies that the file must end in a new line but
    that requirement is relaxed here in parsing.
    """

    def __init__(self, it):
        """
        Create a CoNLL-U file collection of sentences.

        Args:
        it: An iterator of the lines of the CoNLL-U file.
        """
        self._sentences = []

        for sentence in pyconll._parser.iter_sentences(it):
            self._sentences.append(sentence)

    def conll(self):
        """
        Output the Conll object to a CoNLL-U formatted string.

        Returns:
        The CoNLL-U object as a string. This string will end in a newline.
        """
        # Add newlines along with sentence strings so that there is no need to
        # slice potentially long lists or modify strings.
        components = []
        for sentence in self._sentences:
            components.append(sentence.conll())
            components.append('\n\n')

        return ''.join(components)

    def write(self, writable):
        """
        Write the Conll object to something that is writable.

        For simply writing, this method is more efficient than calling conll
        then writing since no string of the entire Conll object is created. The
        final output will include a final newline.

        Args:
        writable: The writable object such as a file. Must have a write method.
        """
        for sentence in self._sentences:
            writable.write(sentence.conll())
            writable.write('\n\n')

    def append(self, sent):
        """
        Add the given sentence to the end of this Conll object.

        Args:
        sent: The Sentence object to add.
        """
        self._sentences.append(sent)

    def insert(self, index, sent):
        """
        Insert the given sentence into the given location.

        This function behaves in the same way as python lists insert.

        Args:
        index: The numeric index to insert the sentence into.
        sent: The sentence to insert.
        """
        self._sentences.insert(index, sent)

    def __contains__(self, other):
        """
        Check if the Conll object has this sentence.

        Args:
        other: The sentence to check for.

        Returns:
        True if this Sentence is exactly in the Conll object. False, otherwise.
        """
        for sentence in self._sentences:
            if other == sentence:
                return True

        return False

    def __iter__(self):
        """
        Allows for iteration over every sentence in the CoNLL-U file.
        """
        for sentence in self._sentences:
            yield sentence

    def __getitem__(self, key):
        """
        Index a sentence by key value.

        Args:
        key: The key to index the sentence by. This key can either be a numeric
        key, or a slice.

        Returns:
        The corresponding sentence if the key is an int or the sentences if the
        key is a slice in the form of another Conll object.

        Raises:
        ValueError if the key is not an integer or slice.
        """
        if isinstance(key, int):
            return self._sentences[key]
        elif isinstance(key, slice):
            sliced_conll = Conll([])
            sliced_conll._sentences = self._sentences[key.start:key.stop:
                                                      key.step]

            return sliced_conll
        else:
            raise ValueError('The key must be an int or a slice.')

    def __setitem__(self, key, sent):
        """
        Set the given location to the Sentence.

        Args:
        key: The location in the Conll file to set to the given sentence. This
            only accepts integer keys and accepts negative indexing.

        Raises:
        IndexError if the key provided is out of range.
        """
        try:
            self._sentences[key] = sent
        except IndexError as e:
            raise IndexError('The index is out of range.') from e

    def __delitem__(self, key):
        """
        Delete the Sentence corresponding with the given key.

        Args:
        key: The info to get the Sentence to delete. Can be the integer position
            in the file, or a slice.

        Raises:
        ValueError if the key is not an integer or a slice.
        """
        if isinstance(key, slice):
            try:
                del self._sentences[key.start:key.stop:key.step]
            except KeyError as e:
                raise KeyError('Slice indices are out of range.') from e
        elif isinstance(key, int):
            del self._sentences[key]
        else:
            raise ValueError('The key must be an int or slice.')

    def __len__(self):
        """
        Returns the number of sentences in the CoNLL-U file.

        Returns:
        The size of the CoNLL-U file in sentences.
        """
        return len(self._sentences)

@@ -3363,36 +3363,35 @@
 Raises:%0A        
-Valu
+Typ
 eError if the ke
@@ -3640,87 +3640,8 @@
 %5Bkey
-.start:key.stop:%0A                                                      key.step
 %5D%0A%0A 
@@ -3699,36 +3699,35 @@
       raise 
-Valu
+Typ
 eError('
 The key must
@@ -3706,39 +3706,45 @@
 aise TypeError('
-The key
+Conll indices
  must be an int 
@@ -3740,26 +3740,31 @@
  be 
-an 
 int
+s
  or 
-a 
 slice
-.
+s, not str
 ')%0A%0A
@@ -4028,243 +4028,55 @@
 ng.%0A
-%0A        Raises:%0A        IndexError if the key provided is out of range.%0A        %22%22%22%0A        try:%0A            self._sentences%5Bkey%5D = sent%0A        except IndexError as e:%0A            raise IndexError('The index is out of range.') from e
+        %22%22%22%0A        self._sentences%5Bkey%5D = sent
 %0A%0A  
@@ -4316,471 +4316,52 @@
 ce.%0A
-%0A        Raises:%0A        ValueError if the key is not an integer or a slice.%0A        %22%22%22%0A        if isinstance(key, slice):%0A            try:%0A                del self._sentences%5Bkey.start:key.stop:key.step%5D%0A            except KeyError as e:%0A                raise KeyError('Slice indices are out of range.') from e%0A        elif isinstance(key, int):%0A            del self._sentences%5Bkey%5D%0A        else:%0A            raise ValueError('The key must be an int or slice.')
+        %22%22%22%0A        del self._sentences%5Bkey%5D
 %0A%0A  

Remove unecessary errors, doc, branching, and slice expansion.