aboutsummaryrefslogtreecommitdiff
path: root/dialoguer/__init__.py
blob: bf1e9780d0c63089c8b3bb531aa032e603bd3bd1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import os
import subprocess
import threading
import socket
import uuid
from .binary_conversion import bin_conv
from .data_type_ref import data_type_dict

HEADER = 2048
PORT = 6011
SERVER = 'localhost'
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)

# could there be a defined sub-class that has all the sockets connection functions?
# then the dialogue class launches and connects and loops
class Dialogue:
	def __init__(self, file_name, wait = True):
		self.file_name = file_name
		self.file_path = os.path.join(os.getcwd(), file_name)
		self.ext = file_name.split('.')[-1]
		self.uuid = str(uuid.uuid4())
		self.conn = None
		self.addr = None
		self.connected = False
		self.active = False
		if wait: 
			self.open()

	def execute_context_script(self):
		context_file = __file__.replace('__init__.py', 'context_script.r')

		subprocess.run(
			f'Rscript {context_file} {self.uuid} {self.file_path}',
			cwd = os.getcwd(),
			start_new_session = True
			)

	def establish_connection(self):
		while not self.connected:
			server.listen()
			self.conn, self.addr = server.accept()
			uuid_chk = self.recv()
			self.connected = self.uuid == uuid_chk
			self.send(self.uuid)
			if not self.connected:
				self.conn.close()
	
	def open(self):
		self._connect = threading.Thread(target=self.establish_connection)
		self._launch = threading.Thread(target=self.execute_context_script)

		self._connect.start()
		self._launch.start()
		self._connect.join()

		data = self.recv(set_data_type=bool)
		self.active = (data == True)
	
	def send(self, data, send_data_type = False):
		if send_data_type:
			data_type_name = type(data)
			data_type_name = data_type_name.__name__
			data_type_name = bin_conv(data_type_name)
			self.conn.send(data_type_name)
		bin_data = bin_conv(data)
		self.conn.send(bin_data)

	# I still want to consolidate the recv_data_type and set_data_type args
	def recv(self, recv_data_type = False, set_data_type = str):
		if recv_data_type:
			data_type_name = self.conn.recv(HEADER)
			while data_type_name == b'\x00':
				data_type_name = self.conn.recv(HEADER)
			data_type_name = bin_conv(data_type_name, str)
			data_type = data_type_dict[data_type_name]
		else:
			data_type = set_data_type

		data = self.conn.recv(HEADER)
		while data == b'\x00':
			data = self.conn.recv(HEADER)
		
		data = bin_conv(data, data_type)

		return data

	def import_variable(self, var_name):
		self.send(var_name, False)
		val = self.recv(True)
		return val

	def evaluate_expression(self, expr):
		pass

	def close(self):
		self.send('!DISCONNECT')
		self._launch.join()
		self.conn.close()
		self.conn = None
		self.addr = None
		self.connected = False
		self.active = False