<commit_before>#!/usr/bin/python
# -*- coding: utf-8 -*-

# Hive Netius System
# Copyright (C) 2008-2012 Hive Solutions Lda.
#
# This file is part of Hive Netius System.
#
# Hive Netius System is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Hive Netius System is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Hive Netius System. If not, see <http://www.gnu.org/licenses/>.

__author__ = "<NAME> <EMAIL>>"
""" The author(s) of the module """

__version__ = "1.0.0"
""" The version of the module """

__revision__ = "$LastChangedRevision$"
""" The revision number of the module """

__date__ = "$LastChangedDate$"
""" The last change date of the module """

__copyright__ = "Copyright (c) 2008-2012 Hive Solutions Lda."
""" The copyright for the module """

__license__ = "GNU General Public License (GPL), Version 3"
""" The license for the module """

import uuid
import types
import thread
import threading

import observer

OPEN = 1
""" The open status value, meant to be used in situations
where the status of the entity is open (opposite of d) """

CLOSED = 2
""" Closed status value to be used in entities which have
no pending structured opened and operations are limited """

PENDING = 3
""" The pending status used for transient states (eg created)
connections under this state must be used carefully """

CHUNK_SIZE = 4096
""" The size of the chunk to be used while received
data from the service socket """

class Connection(observer.Observable):
    """
    Abstract connection object that should encapsulate
    a socket object enabling it to be accessed in much
    more "protected" way avoiding possible sync problems.

    It should also abstract the developer from all the
    select associated complexities adding and removing the
    underlying socket from the selecting mechanism for the
    appropriate operations.
    """

    def __init__(self, owner = None, socket = None, address = None, ssl = False):
        observer.Observable.__init__(self)
        self.status = PENDING
        self.id = str(uuid.uuid4())
        self.connecting = False
        self.upgrading = False
        self.owner = owner
        self.socket = socket
        self.address = address
        self.ssl = ssl
        self.renable = True
        self.wready = True
        self.pending_s = 0
        self.pending = []
        self.pending_lock = threading.RLock()

    def __del__(self):
        observer.Observable.__del__(self)
        self.owner.debug("Connection '%s' deleted from memory" % self.id)

    def open(self, connect = False):
        # in case the current status of the connection is already open
        # it does not make sense to proceed with the opening of the
        # connection as the connection is already open
        if self.status == OPEN: return

        # retrieves the reference to the owner object from the
        # current instance to be used to add the socket to the
        # proper pooling mechanisms (at least for reading)
        owner = self.owner

        # registers the socket for the proper reading mechanisms
        # in the polling infra-structure of the owner
        owner.sub_read(self.socket)
        owner.sub_error(self.socket)

        # adds the current connection object to the list of
        # connections in the owner and the registers it in
        # the map that associates the socket with the connection
        owner.connections.append(self)
        owner.connections_m[self.socket] = self

        # sets the status of the current connection as open
        # as all the internal structures have been correctly
        # updated and not it's safe to perform operations
        self.status = OPEN

        # in case the connect flag is set must set the current
        # connection as connecting indicating that some extra
        # steps are still required to complete the connection
        if connect: self.set_connecting()

        # calls the top level on connection creation handler so that the owner
        # object gets notified about the creation of the connection (open)
        owner.on_connection_c(self)

        # triggers the open event in the current connection so that any listening
        # object is notified about the opening of this connection, as requested by
        # the current netius specification and strategy
        self.trigger("open", self)

    def close(self, flush = False, destroy = True):
        # in case the current status of the connection is closes it does
        # nor make sense to proceed with the closing as the connection
        # is already in the closed state (nothing to be done)
        if self.status == CLOSED: return

        # in case the flush flag is set a different approach is taken
        # where all the pending data is flushed (as possible) before
        # the connection is effectively closed, this is only valid in
        # case the current connection status is open and not connecting
        if flush and self.status == OPEN and not self.connecting:
            return self.close_flush()

        # immediately sets the status of the connection as closed
        # so that no one else changed the current connection status
        # this is relevant to avoid any erroneous situation
        self.status = CLOSED

        # unsets the connecting flag this is for connections that
        # are under the connecting state and that must be reverted
        # to the original not connecting state
        self.connecting = False

        # unsets the write ready flag so that no more write operations
        # are performed as requested by specification (mandatory) this
        # should avoid extra erroneous write operations
        self.wready = False

        # resets the size of the data pending to be send and the clears
        # the list of pending information (invalidation the previous one)
        self.pending_s = 0
        self.pending = []

        # retrieves the reference to the owner object from the
        # current instance to be used to removed the socket from the
        # proper pooling mechanisms (at least for reading)
        owner = self.owner

        # removes the socket from all the polling mechanisms so that
        # interaction with it is no longer part of the selecting mechanism
        self.owner.unsub_all(self.socket)

        # removes the current connection from the list of connection in the
        # owner and also from the map that associates the socket with the
        # proper connection (also in the owner)
        if self in owner.connections: owner.connections.remove(self)
        if self.socket in owner.connections_m: del owner.connections_m[self.socket]

        # closes the socket, using the proper gracefully way so that
        # operations are no longer allowed in the socket, in case there's
        # an error in the operation fails silently (on purpose)
        try: self.socket.close()
        except: pass

        # calls the top level on connection delete handler so that the owner
        # object gets notified about the deletion of the connection (closed)
        owner.on_connection_d(self)

        # triggers the close event in the current connection so that any listening
        # object is notified about the closing of this connection, as requested by
        # the current netius specification and strategy
        self.trigger("close", self)
        
        # in case the destroy flag is set the current object is destroy meaning that
        # for instance the current event registered handlers will no longer be available
        # this is important to avoid any memory leak from circular references, from
        # this moment on the connection is considered disabled (not ready for usage)
        if destroy: self.destroy()

    def close_flush(self):
        self.send("", callback = self._close_callback)

    def upgrade(self, key_file = None, cer_file = None, server = True):
        # in case the current connection is already an ssl oriented one there's<commit_msg>removed extra space<commit_after>#!/usr/bin/python
# -*- coding: utf-8 -*-

# Hive Netius System
# Copyright (C) 2008-2012 Hive Solutions Lda.
#
# This file is part of Hive Netius System.
#
# Hive Netius System is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Hive Netius System is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Hive Netius System. If not, see <http://www.gnu.org/licenses/>.

__author__ = "<NAME> <EMAIL>>"
""" The author(s) of the module """

__version__ = "1.0.0"
""" The version of the module """

__revision__ = "$LastChangedRevision$"
""" The revision number of the module """

__date__ = "$LastChangedDate$"
""" The last change date of the module """

__copyright__ = "Copyright (c) 2008-2012 Hive Solutions Lda."
""" The copyright for the module """

__license__ = "GNU General Public License (GPL), Version 3"
""" The license for the module """

import uuid
import types
import thread
import threading

import observer

OPEN = 1
""" The open status value, meant to be used in situations
where the status of the entity is open (opposite of d) """

CLOSED = 2
""" Closed status value to be used in entities which have
no pending structured opened and operations are limited """

PENDING = 3
""" The pending status used for transient states (eg created)
connections under this state must be used carefully """

CHUNK_SIZE = 4096
""" The size of the chunk to be used while received
data from the service socket """

class Connection(observer.Observable):
    """
    Abstract connection object that should encapsulate
    a socket object enabling it to be accessed in much
    more "protected" way avoiding possible sync problems.

    It should also abstract the developer from all the
    select associated complexities adding and removing the
    underlying socket from the selecting mechanism for the
    appropriate operations.
    """

    def __init__(self, owner = None, socket = None, address = None, ssl = False):
        observer.Observable.__init__(self)
        self.status = PENDING
        self.id = str(uuid.uuid4())
        self.connecting = False
        self.upgrading = False
        self.owner = owner
        self.socket = socket
        self.address = address
        self.ssl = ssl
        self.renable = True
        self.wready = True
        self.pending_s = 0
        self.pending = []
        self.pending_lock = threading.RLock()

    def __del__(self):
        observer.Observable.__del__(self)
        self.owner.debug("Connection '%s' deleted from memory" % self.id)

    def open(self, connect = False):
        # in case the current status of the connection is already open
        # it does not make sense to proceed with the opening of the
        # connection as the connection is already open
        if self.status == OPEN: return

        # retrieves the reference to the owner object from the
        # current instance to be used to add the socket to the
        # proper pooling mechanisms (at least for reading)
        owner = self.owner

        # registers the socket for the proper reading mechanisms
        # in the polling infra-structure of the owner
        owner.sub_read(self.socket)
        owner.sub_error(self.socket)

        # adds the current connection object to the list of
        # connections in the owner and the registers it in
        # the map that associates the socket with the connection
        owner.connections.append(self)
        owner.connections_m[self.socket] = self

        # sets the status of the current connection as open
        # as all the internal structures have been correctly
        # updated and not it's safe to perform operations
        self.status = OPEN

        # in case the connect flag is set must set the current
        # connection as connecting indicating that some extra
        # steps are still required to complete the connection
        if connect: self.set_connecting()

        # calls the top level on connection creation handler so that the owner
        # object gets notified about the creation of the connection (open)
        owner.on_connection_c(self)

        # triggers the open event in the current connection so that any listening
        # object is notified about the opening of this connection, as requested by
        # the current netius specification and strategy
        self.trigger("open", self)

    def close(self, flush = False, destroy = True):
        # in case the current status of the connection is closes it does
        # nor make sense to proceed with the closing as the connection
        # is already in the closed state (nothing to be done)
        if self.status == CLOSED: return

        # in case the flush flag is set a different approach is taken
        # where all the pending data is flushed (as possible) before
        # the connection is effectively closed, this is only valid in
        # case the current connection status is open and not connecting
        if flush and self.status == OPEN and not self.connecting:
            return self.close_flush()

        # immediately sets the status of the connection as closed
        # so that no one else changed the current connection status
        # this is relevant to avoid any erroneous situation
        self.status = CLOSED

        # unsets the connecting flag this is for connections that
        # are under the connecting state and that must be reverted
        # to the original not connecting state
        self.connecting = False

        # unsets the write ready flag so that no more write operations
        # are performed as requested by specification (mandatory) this
        # should avoid extra erroneous write operations
        self.wready = False

        # resets the size of the data pending to be send and the clears
        # the list of pending information (invalidation the previous one)
        self.pending_s = 0
        self.pending = []

        # retrieves the reference to the owner object from the
        # current instance to be used to removed the socket from the
        # proper pooling mechanisms (at least for reading)
        owner = self.owner

        # removes the socket from all the polling mechanisms so that
        # interaction with it is no longer part of the selecting mechanism
        self.owner.unsub_all(self.socket)

        # removes the current connection from the list of connection in the
        # owner and also from the map that associates the socket with the
        # proper connection (also in the owner)
        if self in owner.connections: owner.connections.remove(self)
        if self.socket in owner.connections_m: del owner.connections_m[self.socket]

        # closes the socket, using the proper gracefully way so that
        # operations are no longer allowed in the socket, in case there's
        # an error in the operation fails silently (on purpose)
        try: self.socket.close()
        except: pass

        # calls the top level on connection delete handler so that the owner
        # object gets notified about the deletion of the connection (closed)
        owner.on_connection_d(self)

        # triggers the close event in the current connection so that any listening
        # object is notified about the closing of this connection, as requested by
        # the current netius specification and strategy
        self.trigger("close", self)

        # in case the destroy flag is set the current object is destroy meaning that
        # for instance the current event registered handlers will no longer be available
        # this is important to avoid any memory leak from circular references, from
        # this moment on the connection is considered disabled (not ready for usage)
        if destroy: self.destroy()

    def close_flush(self):
        self.send("", callback = self._close_callback)

    def upgrade(self, key_file = None, cer_file = None, server = True):
        # in case the current connection is already an ssl oriented one there's
{'fraction_non_alphanumeric': 0.05664849490400569, 'fraction_numerical': 0.003792367859682389, 'mean_word_length': 2.7596346625083537, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, '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': '321264', 'n_tokens_mistral': 4140, 'n_tokens_neox': 3951, 'n_words': 2101}