<commit_before>###############################################################################
#
# Copyright 2011 <NAME>
#
# 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.
#
###############################################################################

###############################################################################
# Imports
###############################################################################

import errno
import os
import socket

from pants.engine import Engine


###############################################################################
# Logging
###############################################################################

import logging
log = logging.getLogger("pants")


###############################################################################
# Channel Class
###############################################################################

class Channel(object):
    """
    A raw socket wrapper object.
    
    This class wraps a raw socket object and provides a basic API to
    make socket programming significantly simpler. It handles read,
    write and exception events, has a level of inbuilt error handling
    and calls placeholder methods when certain events occur. The Channel
    class can be subclassed directly, but it is recommended that the
    Server, Connection and Client classes be used to develop networking
    code as they provide slightly less generic APIs.
    """
    def __init__(self, socket=None):
        """
        Initialises the channel object.
        
        Args:
            socket: A pre-existing socket that this channel should wrap.
                Optional.
        """
        # Socket
        self._socket = socket or self._socket_create()
        self._socket.setblocking(False)
        self.fileno = self._socket.fileno()
        self.remote_addr = (None, None)
        self.local_addr = (None, None)
        
        # Internal state
        self._connected = False
        self._connecting = False
        self._listening = False
        self._closing = False
        
        # Input
        self.read_delimiter = None # String, integer or None.
        self._read_amount = 4096
        self._read_buffer = ""
        
        # Output
        self._write_buffer = ""
        self._secondary_write_buffer = ""
        self._write_file = None
        self._write_file_left = None
        self._write_file_chunk = 65536
        
        # Initialisation
        self._events = Engine.ERROR
        if self.readable():
            self._events |= Engine.READ
        if self.writable():
            self._events |= Engine.WRITE
        Engine.instance().add_channel(self)
    
    ##### General Methods #####################################################
    
    def active(self):
        """
        Check if the channel is currently active.
        
        Returns:
            True or False
        """
        return self._socket and (self._connected or self._listening or self._connecting)
    
    def readable(self):
        """
        Check if the channel is currently readable.
        
        Returns:
            True or False
        """
        return not self._closing
    
    def writable(self):
        """
        Check if the channel is currently writable.
        
        Returns:
            True or False
        """
        return len(self._write_buffer) > 0 or self._write_file
    
    def connect(self, host, port):
        """
        Connects to the given host and port.
        
        Args:
            host: The hostname to connect to.
            port: The port to connect to.
        
        Returns:
            The Channel object.
        """
        if self.active():
            log.warning("Channel.connect() called on active channel %d." % self.fileno)
            return
        
        self._socket_connect(host, port)
        
        return self
    
    def listen(self, port=8080, host='', backlog=1024):
        """
        Begins listening on the given host and port.
        
        Args:
            port: The port to listen on. Defaults to 8080.
            host: The hostname to listen on. Defaults to ''.
            backlog: The maximum number of queued connections. Defaults
                to 1024.
        
        Returns:
            The Channel object.
        """
        if self.active():
            log.warning("Channel.listen() called on active channel %d." % self.fileno)
            return
        
        self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self._socket_bind(host, port)
        self._socket_listen(backlog)
        self._update_addr()
        
        return self
    
    def close(self):
        """
        Close the socket.
        
        Currently pending data will be sent, any further data will not
        be sent.
        """
        if not self.active():
            return
        
        if self.writable():
            self._closing = True
        else:
            self.close_immediately()
    <commit_msg>Fixed: Channel.listen and Channel.connect returned None if they were already active.<commit_after>###############################################################################
#
# Copyright 2011 <NAME>
#
# 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.
#
###############################################################################

###############################################################################
# Imports
###############################################################################

import errno
import os
import socket

from pants.engine import Engine


###############################################################################
# Logging
###############################################################################

import logging
log = logging.getLogger("pants")


###############################################################################
# Channel Class
###############################################################################

class Channel(object):
    """
    A raw socket wrapper object.
    
    This class wraps a raw socket object and provides a basic API to
    make socket programming significantly simpler. It handles read,
    write and exception events, has a level of inbuilt error handling
    and calls placeholder methods when certain events occur. The Channel
    class can be subclassed directly, but it is recommended that the
    Server, Connection and Client classes be used to develop networking
    code as they provide slightly less generic APIs.
    """
    def __init__(self, socket=None):
        """
        Initialises the channel object.
        
        Args:
            socket: A pre-existing socket that this channel should wrap.
                Optional.
        """
        # Socket
        self._socket = socket or self._socket_create()
        self._socket.setblocking(False)
        self.fileno = self._socket.fileno()
        self.remote_addr = (None, None)
        self.local_addr = (None, None)
        
        # Internal state
        self._connected = False
        self._connecting = False
        self._listening = False
        self._closing = False
        
        # Input
        self.read_delimiter = None # String, integer or None.
        self._read_amount = 4096
        self._read_buffer = ""
        
        # Output
        self._write_buffer = ""
        self._secondary_write_buffer = ""
        self._write_file = None
        self._write_file_left = None
        self._write_file_chunk = 65536
        
        # Initialisation
        self._events = Engine.ERROR
        if self.readable():
            self._events |= Engine.READ
        if self.writable():
            self._events |= Engine.WRITE
        Engine.instance().add_channel(self)
    
    ##### General Methods #####################################################
    
    def active(self):
        """
        Check if the channel is currently active.
        
        Returns:
            True or False
        """
        return self._socket and (self._connected or self._listening or self._connecting)
    
    def readable(self):
        """
        Check if the channel is currently readable.
        
        Returns:
            True or False
        """
        return not self._closing
    
    def writable(self):
        """
        Check if the channel is currently writable.
        
        Returns:
            True or False
        """
        return len(self._write_buffer) > 0 or self._write_file
    
    def connect(self, host, port):
        """
        Connects to the given host and port.
        
        Args:
            host: The hostname to connect to.
            port: The port to connect to.
        
        Returns:
            The Channel object.
        """
        if self.active():
            log.warning("Channel.connect() called on active channel %d." % self.fileno)
            return self
        
        self._socket_connect(host, port)
        
        return self
    
    def listen(self, port=8080, host='', backlog=1024):
        """
        Begins listening on the given host and port.
        
        Args:
            port: The port to listen on. Defaults to 8080.
            host: The hostname to listen on. Defaults to ''.
            backlog: The maximum number of queued connections. Defaults
                to 1024.
        
        Returns:
            The Channel object.
        """
        if self.active():
            log.warning("Channel.listen() called on active channel %d." % self.fileno)
            return self
        
        self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self._socket_bind(host, port)
        self._socket_listen(backlog)
        self._update_addr()
        
        return self
    
    def close(self):
        """
        Close the socket.
        
        Currently pending data will be sent, any further data will not
        be sent.
        """
        if not self.active():
            return
        
        if self.writable():
            self._closing = True
        else:
            self.close_immediately()
    
{'fraction_non_alphanumeric': 0.18704649287825853, 'fraction_numerical': 0.006270715757412882, 'mean_word_length': 2.160815402038505, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, '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': '758057', 'n_tokens_mistral': 2672, 'n_tokens_neox': 2549, 'n_words': 896}