<commit_before>#
# Copyright (c) 2016 <NAME> <<EMAIL>>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#

import os
import sys
import socket
import threading
from functools import wraps

BEHEM0TH_PATH = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
sys.path.append(os.path.join(BEHEM0TH_PATH, 'watchdog/src'))
sys.path.append(os.path.join(BEHEM0TH_PATH, 'pathtools'))

from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler, FileModifiedEvent

from behem0th import utils, log
from behem0th.RequestHandler import RequestHandler


IGNORE_LIST = [
	'.git/',
	'.DS_Store'
]

DEFAULT_PORT = 3078


def synchronized(fn):
	@wraps(fn)
	def wrap(*args, **kwargs):
		lock = args[0]._rlock
		with lock:
			return fn(*args, **kwargs)

	return wrap


class _FsEventHandler(PatternMatchingEventHandler):
	def __init__(self, client):
		super().__init__(ignore_patterns=client._ignore_list)
		self.client = client


	def on_any_event(self, event):
		# Ignore DirModifiedEvent's completely.
		if event.event_type == 'modified' and event.is_directory:
			return

		event_handled = self.client._handle_fsevent(event)
		log.info_v('Got event {0} - was handled? {1}', event, event_handled)

		# On macOS, watchdog only produces a file-created event,
		# on Linux however also a file-modified event is generated.
		if sys.platform == 'darwin':
			if event_handled and event.event_type == 'created' and not event.is_directory:
				self.client._handle_fsevent(FileModifiedEvent(event.src_path))


class _AcceptWorker(threading.Thread):
	def __init__(self, **kwargs):
		super().__init__()
		self.name = 'accept-worker'
		self.kwargs = kwargs
		self.daemon = True


	def run(self):
		client = self.kwargs['client']
		address = self.kwargs['address']

		accept_sock = socket.socket()
		accept_sock.bind(address)
		accept_sock.listen()

		log.info_v('Started listening on {0}:{1}', address[0], address[1])

		while 1:
			sock, address = accept_sock.accept()
			RequestHandler(sock=sock, address=address, client=client).start()


class Client:
	"""The main interface for behem0th

	This class can either act as a client which connects to a behem0th server
	or as a server to which behem0th clients can connect.<commit_msg>Pass a argument to socket.listen()<commit_after>#
# Copyright (c) 2016 <NAME> <<EMAIL>>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#

import os
import sys
import socket
import threading
from functools import wraps

BEHEM0TH_PATH = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
sys.path.append(os.path.join(BEHEM0TH_PATH, 'watchdog/src'))
sys.path.append(os.path.join(BEHEM0TH_PATH, 'pathtools'))

from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler, FileModifiedEvent

from behem0th import utils, log
from behem0th.RequestHandler import RequestHandler


IGNORE_LIST = [
	'.git/',
	'.DS_Store'
]

DEFAULT_PORT = 3078


def synchronized(fn):
	@wraps(fn)
	def wrap(*args, **kwargs):
		lock = args[0]._rlock
		with lock:
			return fn(*args, **kwargs)

	return wrap


class _FsEventHandler(PatternMatchingEventHandler):
	def __init__(self, client):
		super().__init__(ignore_patterns=client._ignore_list)
		self.client = client


	def on_any_event(self, event):
		# Ignore DirModifiedEvent's completely.
		if event.event_type == 'modified' and event.is_directory:
			return

		event_handled = self.client._handle_fsevent(event)
		log.info_v('Got event {0} - was handled? {1}', event, event_handled)

		# On macOS, watchdog only produces a file-created event,
		# on Linux however also a file-modified event is generated.
		if sys.platform == 'darwin':
			if event_handled and event.event_type == 'created' and not event.is_directory:
				self.client._handle_fsevent(FileModifiedEvent(event.src_path))


class _AcceptWorker(threading.Thread):
	def __init__(self, **kwargs):
		super().__init__()
		self.name = 'accept-worker'
		self.kwargs = kwargs
		self.daemon = True


	def run(self):
		client = self.kwargs['client']
		address = self.kwargs['address']

		accept_sock = socket.socket()
		accept_sock.bind(address)
		accept_sock.listen(1)

		log.info_v('Started listening on {0}:{1}', address[0], address[1])

		while 1:
			sock, address = accept_sock.accept()
			RequestHandler(sock=sock, address=address, client=client).start()


class Client:
	"""The main interface for behem0th

	This class can either act as a client which connects to a behem0th server
	or as a server to which behem0th clients can connect.
{'fraction_non_alphanumeric': 0.09314775160599571, 'fraction_numerical': 0.007494646680942184, 'mean_word_length': 4.890990990990991, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, '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': '151969', 'n_tokens_mistral': 2089, 'n_tokens_neox': 1942, 'n_words': 703}