def extract_strings_from_filename(self, filename): output_dir = self._get_output_directory() self._run_genstrings_command_for_file(filename, output_dir) full_paths = [] for file in os.listdir(output_dir): full_paths.append(os.path.join(output_dir, file)) strings_parser = Strings() return_values = \ strings_parser.extract_strings_from_files(full_paths) shutil.rmtree(output_dir) return return_values
def main(): options = Arguments().get_args() binary = Binary(options) exec_sections = binary.get_exec_sections() data_sections = binary.get_data_sections() gadgets = Gadgets(exec_sections, options) gadgets.pretty_print_gadgets() strings = Strings(exec_sections + data_sections) strings.pretty_print_strings() ropchain = Ropchain(gadgets.get_gadgets(), binary.get_data_section_offset()) ropchain.pretty_print_chain()
def __init__(self): filename = getSettingsFile() if not os.path.exists(filename): lang = dialogs.select_language(None, ["english", "czech"]) if not lang: sys.exit(1) photodir = getDirectory() if not photodir: sys.exit(1) with open(filename, "w+") as f: f.write(DEFAULT_SETTINGS.format(photodir, lang)) data = "" with open(filename, "r") as f: data = f.read() self.settings = {} for line in data.splitlines(): if not line or line.startswith("#"): continue key, value = line.split("=", 1) self.settings[key] = value self.strings = Strings( getStringsFile(self["language"] if "language" in self.settings else "english"))
class TestStrings(TestCase): def setUp(self): self.strings = Strings() def test_data(self): self.assertTrue(self.strings.data, list) def test_get(self): self.strings.data = {"test_key": "test_string"} self.assertIs(self.strings.get("test_key"), "test_string") def test_get_with_params(self): self.strings.data = {"test_key": "test_string_with_param_<?>"} self.assertEqual(self.strings.get("test_key", "X"), "test_string_with_param_X")
def xmlbeautify_page(): return render_template('index.html', s=Strings(g.lang_code))
def baseconv_page(): return render_template('index.html', s=Strings(g.lang_code))
def httpheader_page(): return render_template('index.html', s=Strings(g.lang_code))
def diff_index(): return render_template('diff_index.html', s=Strings(g.lang_code))
class BaseState(object): """ This class is a parent-class for all state handlers, it provides: - interface to Google Translations API - interface to our own phrases/responses - automatically translates our strings to the language of the user - automatically adds pictures to the chosen intents/conversation steps/questions - interface to the database - interface to the NLU (Natural Language Understanding unit - https://github.com/HumanbiOS/rasa) - automatic requests queueing - automatic database updates for the `User` object Note 0: In the text there are some special words: $(name) - refers to the random meaningful (or not) string that came to your mind $(root) - refers to the project directory Note 1: Server will pick up files and extract state classes from them, you don't need to worry about "registering state", there is no hardcoded list The important detail is that you **must** put state.py with the state handler to the $(root)/fsm/states folder. Note 2: It's a better practise to put each state handler in its own file. Naming Conventions: - name of the python class - `$(name)State` Example: ` class MyBeautifulState:` ` class BasicQuestionsState:` - name of the file - *snake lower case* of $(name). "state" might be omitted (filename matters only to avoid confusions, refer to note 1) Example: `my_beautiful_state.py` `basic_questions.py` """ HEADERS = {"Content-Type": "application/json"} # This variable allows to ignore `entry()` when needed has_entry = True # @Important: instantiate important classes tr = Translator() db = Database() nlu = NLUWorker(tr) STRINGS = Strings(tr, db) # Data buffer that is assigned to when the class is initialized, stores reference to the relevant Botsociety Data bots_data = None # Media path and folder media_folder = "media" media_path = os.path.join(ROOT_PATH, media_folder) if not os.path.exists(media_path): os.mkdir(media_path) # Prepare state def __init__(self): # Keeps list of tasks self.tasks = list() self.random_tasks = list() # Keeps execution queue self.execution_queue = list() # Create language variable self.__language = None self.strings = None def set_language(self, value: str): """ This method sets language to a current state If language is None - base language version is english Args: value (str): language code of the user's country """ self.__language = value or "en" self.strings = StringAccessor(self.__language, self.STRINGS) async def wrapped_entry(self, context: Context, user: User): """ This method is executed when user enters State for the first time, if `has_entry` variable is set to True. It is a wrapper for state-author-controlled `entry` method. Args: context (Context): holds parsed and verified request, with auto-filled default values user (User): user object that is stored directly in the database """ # Set language self.set_language(user['language']) # Wrap base method to avoid breaking server try: # Execute state method status = await self.entry(context, user, self.db) except Exception as e: # Do not commit to database if something went wrong status = OK(commit=False) # Log exception logging.exception(e) # Commit changes to database if status.commit: await self.db.commit_user(user=user) # @Important: Fulfill text promises if self.strings.promises: await self.strings.fill_promises() # @Important: Since we call this always, check if the call is actually needed if self.tasks: # @Important: collect all requests _results = await self._collect() # @Important: Execute all queued jobs if self.execution_queue: await self._execute_tasks() return status async def wrapped_process(self, context: Context, user: User): """ This method is executed when user enters State for second or any consequent time, or for the first time if `has_entry` variable is set to False. It is a wrapper for state-author-modified `process` method. Args: context (Context): holds parsed and verified request, with auto-filled default values user (User): user object that is stored directly in the database """ # Set language self.set_language(user['language']) # Wrap base method to avoid breaking server try: # Execute state method status = await self.process(context, user, self.db) except Exception as e: # Do not commit to database if something went wrong status = OK(commit=False) # Log exception logging.exception(e) # Commit changes to database if status.commit: await self.db.commit_user(user=user) # @Important: Fulfill text promises if self.strings.promises: await self.strings.fill_promises() # @Important: Since we call this always, check if the call is actually needed if self.tasks: # @Important: collect all requests await self._collect() # @Important: Execute all queued jobs if self.execution_queue: await self._execute_tasks() return status # Actual state method to be written for the state async def entry(self, context: Context, user: User, db): """ The method handles each interaction when user enters your state Args: context (Context): context object of the request user (User): user object from database corresponding to the user who sent message db (Database): database wrapper object """ return OK # Actual state method to be written for the state async def process(self, context: Context, user: User, db): """ The method handles each interaction with user (except first interaction) Args: context (Context): context object of the request user (User): user object from database corresponding to the user who sent message db (Database): database wrapper object """ return OK def parse_button(self, raw_text: str, truncated=False, truncation_size=20, verify=None) -> Button: """ Function compares input text to all available strings (of user's language) and if finds matching - returns Button object, which has text and key attributes, where text is raw_text and key is a key of matched string from strings.json Args: raw_text (str): just user's message truncated (bool): option to look for not full matches (only first `n` characters). Defaults to False. truncation_size (int): number of sequential characters to match. Defaults to 20. verify (list, set): a custom object that is used instead of global language object (e.g. you want a match from the list of specific buttons) """ btn = Button(raw_text) lang_obj = self.STRINGS.cache.get(self.__language) # Make sure that certain language file exists if lang_obj and verify: lang_obj = [(key, lang_obj[key]) for key in verify] elif lang_obj: lang_obj = lang_obj.items() for k, v in lang_obj: if v == raw_text or (truncated and len(v) > truncation_size and v[:truncation_size] == raw_text[:truncation_size]): # [DEBUG] # logging.info(value) btn.set_key(k) break return btn # Parse intent of single-formatted string, comparing everything but inserted # Returns True -> intent matched # Returns None or False -> intent didn't match def parse_fstring(self, raw_text: str, promise: TextPromise, item1: str = "{", item2: str = "}"): """ Method lets you compare "filled" f-string with "un-filled" one to identify intent, which is not possible with simple `==` comparison, because the f-string is *actually* "filled". Compares sub-strings to the "{" char and after the "}" char, exclusively. Args: raw_text (str): raw input, which is "filled" string promise (TextPromise): cached input, "un-filled" string item1 (str): object to compare from start to position of it in the strings *exclusively* item2 (str): object to compare from its position to the end of the strings *exclusively* """ if promise.value and isinstance(promise.value, str): # Find where "{" or "}" should've been, then use it to go one char left or right, accordingly i1 = promise.value.find(item1) i2 = promise.value.find(item2) if i1 != -1 and i2 != -1: # Find from the end, so can use negative index # Can't just measure from the start, because there will be inserted text of random length i2 = len(promise.value) - i2 return raw_text[:i1] == promise.value[:i1] and raw_text[ -i2 + 1:] == promise.value[-i2 + 1:] # @Important: easy method to prepare context def set_data(self, context: Context, question: dict, avoid_buttons: list = None): # Change value from None to empty list for the "in" operator avoid_buttons = avoid_buttons or [] # Set according text context['request']['message']['text'] = self.strings[ question["text_key"]] # Always have buttons context['request']['has_buttons'] = True context['request']['buttons_type'] = "text" # If not a free question -> add it's buttons if not question["free_answer"]: context['request']['buttons'] = [ {"text": self.strings[button["text_key"]]} for button in question["buttons"] \ if button["text_key"] not in avoid_buttons ] else: context['request']['buttons'] = [] # Always add edge buttons context['request']['buttons'] += [{ "text": self.strings['back'] }, { "text": self.strings['stop'] }] # Add file if needed media = question.get('image') if media: context['request']['has_file'] = True context['request']['file'] = [{"payload": media}] # @Important: 1) find better way with database # @Important: 2) What if we do it in non blocking asyncio.create_task (?) # @Important: But on the other hand, we can't relay on the file status # @Important: for example if next call needs to upload it somewhere # @Important: If you deal with reliability and consistency - great optimisation async def download_by_url(self, url, *folders, filename): """ Downloads any file to the given directory with given filename from the url, in asynchronous way (not-blocking-ish). """ # TODO: Use async executor for real non-blocking? # TODO: Or, do we really need this method? # Make sure file exists if not self.exists(*folders): # Create folder on the path os.mkdir(os.path.join(self.media_path, *folders)) # Full file path with filename filepath = os.path.join(self.media_path, *folders, filename) # Initiate aiohttp sessions, get file async with ClientSession() as session: async with session.get(url) as response: # Open file with aiofiles and start steaming bytes, write to the file logging.debug(f"Downloading file: {url} to {filepath}") async with aiofiles.open(filepath, 'wb') as f: async for chunk in response.content.iter_any(): await f.write(chunk) logging.debug(f"Finished download [{filepath}]") return filepath # @Important: check if downloaded file exist def exists(self, *args): """ Checks for the file in the passed directory/filepath, shortcut for the os `exists` and `join` methods """ return os.path.exists(os.path.join(self.media_path, *args)) # @Important: high level access to translation module # @Important: note, though, that we shouldn't abuse translation api # @Important: because a) it's not good enough, b) it takes time to make # @Important: a call to the google cloud api async def translate(self, text: str, target: str) -> str: """ Method is wrapper for translation_text from translation module. Simply returns translated text for the target language. Good usage example if translating text between users. Args: text (str): message to translate target (str): target language (ISO 639-1 code) """ return await self.tr.translate_text(text, target) # @Important: command to actually send all collected requests from `process` or `entry` async def _collect(self): results = list() async with ClientSession(json_serialize=lambda o: json.dumps( o, cls=PromisesEncoder)) as session: # @Important: Since asyncio.gather order is not preserved, we don't want to run them concurrently # @Important: so, gather tasks that were tagged with "allow_gather". # @Important: Group tasks by the value of "size" for the sake of not hitting front end too hard size = 30 for coeff in range(len(self.random_tasks[::size])): results.extend(await asyncio.gather( *(self._send(r_task, session) for r_task in self.random_tasks[size * coeff:size * (coeff + 1)]))) # Send ordinary tasks for each_task in self.tasks: res = await self._send(each_task, session) results.append(res) return results # @Important: Real send method, takes SenderTask as argument async def _send(self, task: SenderTask, session: ClientSession): # Takes instance data holder object with the name from the tokens storage, extracts url url = tokens[task.service].url # Unpack context, set headers (content-type: json) async with session.post(url, json=task.context, headers=self.HEADERS) as resp: # If reached server - log response if resp.status == 200: pass # [DEBUG] #result = await resp.json() #if result: # logging.info(f"Sending task status: {result}") # return result #else: # logging.info(f"Sending task status: No result") # Otherwise - log error else: logging.error( f"[ERROR]: Sending task (service={task.service}, context={task.context}) status {await resp.text()}" ) # @Important: `send` METHOD THAT ALLOWS TO SEND PAYLOAD TO THE USER def send(self, to_entity: Union[User, str], context: Context, allow_gather=False): """ Method creates task that sends context['request'] to the to_user User after executing your code inside state. Args: to_entity (User, str): user object to send message to, or just service name context (Context): request context that is send to the user. The object is deep copied so it can't be changed further in code (reliable consistency for multiple requests) """ # @Important: [Explanation to the code below]: # @Important: maybe add some queue of coroutines and dispatch them all when handler return status (?) # @Important: or just dispatch them via asyncio.create_task so it will be more efficient (?) # @Important: reasoning: # @Important: simple way: server -> request1 -> status1 -> request2 -> status2 -> request3 -> status3 # @Important: this way: server -> gather(request1, request2, request3) -> log(status1, status2, status3) if isinstance(to_entity, str): service = to_entity else: service = to_entity['via_instance'] task = SenderTask(service, copy.deepcopy(context.__dict__['request'])) if allow_gather: self.random_tasks.append(task) else: self.tasks.append(task) async def _execute_tasks(self): results = await asyncio.gather(*[ exec_task.func(*exec_task.args, **exec_task.kwargs) for exec_task in self.execution_queue ]) return results def create_task(self, func, *args, **kwargs): """ Method executes async function (with given args and kwargs) immediately after processing state. Args: func (Async Func): function to be executed args (Any): args to be passed into the func kwargs (Any): kwargs to be passed into the func """ self.execution_queue.append(ExecutionTask(func, args, kwargs)) def create_conversation(self, user1: User, user2: User, context: Context, message: Optional[str] = None) -> None: user1['context']['conversation'] = { "user_id": user2['user_id'], "via_instance": user2['via_instance'], "type": user2['type'] } user2['context']['conversation'] = { "user_id": user1['user_id'], "via_instance": user1['via_instance'], "type": user1['type'] } # Send message to them if message or message is None: if message is None: message = "You've just started realtime conversation. Just start typing to talk to them!" context['request']['user']['user_id'] = 1 context['request']['user']['first_name'] = "HumanBios" context['request']['chat']['chat_id'] = user1['user_id'] context['request']['message']['text'] = message self.send(user1, context) context['request']['chat']['chat_id'] = user2['user_id'] self.send(user2, context) user1['states'].append("ConversationState") user2['states'].append("ConversationState")
def _create_strings_parser(self): return Strings()
def unie_index(): return render_template('unie_index.html', s=Strings(g.lang_code))
def __init__(self): """ Initializes the graphical user interface """ # main interface object self.parent = Tk() self.parent.state = False # strings manager strings = Strings() self._ = strings.get # theme style = ThemedStyle(self.parent) style.set_theme("arc") # button style style.configure("TButton", font=self.button_font_family) # special button style style.configure(self.special_button_style, font=(self.special_button_font_family, self.special_button_font_size, self.special_button_font_weight)) # make buttons change foreground when hovered style.map("TButton", foreground=[("active", self.special_button_active)]) # root window initialization Frame.__init__(self, self.parent) w = config.get_int("minimum_window_width", 1280) # minimum width for the Tk parent h = config.get_int("minimum_window_height", 800) # minimum height for the Tk parent # get screen width and height ws = self.parent.winfo_screenwidth() # width of the screen hs = self.parent.winfo_screenheight() # height of the screen self.parent.geometry("%dx%d+0+0" % (ws, hs)) # set the dimensions of the window self.parent.minsize(w, h) # minimum size of the window # window title self.parent.title(self.window_title) # menu bar self.menu_bar = Menu(self.parent, font=self.menu_font_family) self.file_menu = Menu(self.menu_bar, tearoff=0, font=self.menu_font_family) self.menu_bar.add_cascade(label=self._("menu.cascade.file"), menu=self.file_menu) self.edit_menu = Menu(self.menu_bar, tearoff=0, font=self.menu_font_family) self.menu_bar.add_cascade(label=self._("menu.cascade.edit"), menu=self.edit_menu) self.view_menu = Menu(self.menu_bar, tearoff=0, font=self.menu_font_family) self.menu_bar.add_cascade(label=self._("menu.cascade.view"), menu=self.view_menu) self.view_menu.add_command(label=self._("menu.zoom_in"), accelerator="Ctrl++", command=self.zoom_in) self.view_menu.add_command(label=self._("menu.zoom_out"), accelerator="Ctrl+-", command=self.zoom_out) self.filter_menu = Menu(self.menu_bar, tearoff=0, font=self.menu_font_family) self.menu_bar.add_cascade(label=self._("menu.cascade.filter"), menu=self.filter_menu) self.taxonomy_menu = Menu(self.menu_bar, tearoff=0, font=self.menu_font_family) self.menu_bar.add_cascade(label=self._("menu.cascade.taxonomy"), menu=self.taxonomy_menu) self.parent.config(menu=self.menu_bar) # make the frame take the whole window self.pack(fill=BOTH, expand=1) # input frame self.input_frame = None # output frame self.output_frame = Frame(self) self.output_frame.pack(fill=BOTH, anchor=N, expand=1) self.output_frame.grid_propagate(False) # ensure a consistent GUI size self.output_frame.grid_rowconfigure( 0, weight=30) # implement stretchability self.output_frame.grid_rowconfigure( 1, weight=1) # implement stretchability self.output_frame.grid_columnconfigure(0, weight=1) self.text = Text(self.output_frame, borderwidth=3, relief=SUNKEN, cursor="arrow", selectbackground=self.select_background, inactiveselectbackground=self.select_background) # Text widget self.text.grid(row=0, column=0, sticky="nsew", padx=self.padding, pady=(self.padding, 0)) self.text.config(font=(self.text_font_family, self.text_font_size), undo=True, wrap=WORD, bg=self.text_background, fg=self.text_foreground, state=DISABLED) # create a Scrollbar and associate it with text self.scrollbar = Scrollbar(self.output_frame, command=self.text.yview) self.scrollbar.grid(row=0, rowspan=3, column=1, sticky=NSEW) self.text["yscrollcommand"] = self.scrollbar.set # status bar self.status = Label(self.output_frame, font=(self.label_font_family, self.label_font_size, "bold")) self.status.grid(row=1, column=0, pady=0) # binds any typing to the command input field to the update_commands method sv = StringVar() sv.trace("w", lambda name, index, mode, sv=sv: self.update_commands()) # input frame self.input_frame = Frame(self) self.input_frame.pack(fill=X, side=BOTTOM) # makes the command input field self.entry = Entry(self.input_frame, font=(self.entry_font_family, self.entry_font_size), textvariable=sv, state=DISABLED) self.entry.bind( "<Return>", self.return_pressed ) # binds the Return key to the return_pressed() method self.entry.bind( "<KP_Enter>", self.return_pressed ) # binds the Return key to the return_pressed() method self.entry.bind( "<Tab>", self.tab_pressed) # binds the Tab key to the tab_pressed() method self.entry.pack(fill=X, side=BOTTOM, padx=2, pady=2) # places the input field self.entry.focus_set() # sets the focus on the input field # creates the frame containing buttons self.commands = Frame(self.input_frame) self.commands.pack(fill=X, side=BOTTOM) self.prompt = StringVar() self.prompt_label = Label(self.commands, font=(self.prompt_font_family, self.prompt_font_size, self.prompt_font_weight), textvariable=self.prompt) self.prompt_label.pack(side=LEFT, padx=(10, 15), pady=10) # creates the frame containing special buttons self.special_commands = Frame(self.input_frame) self.special_commands.pack(fill=X, side=BOTTOM) # default bindings self.parent.bind(config.get_string("toggle_fullscreen", "<F11>"), lambda event: self.toggle_fullscreen()) self.parent.bind(config.get_string("exit_prompt", "<Escape>"), lambda event: self.exit_prompt()) self.parent.bind(config.get_string("zoom_in", "<Control-KP_Add>"), lambda event: self.zoom_in()) self.parent.bind( config.get_string("zoom_out", "<Control-KP_Subtract>"), lambda event: self.zoom_out()) # binding mouse clicks and movement self.text.bind("<Button-1>", self.record_click) self.text.bind("<Button-2>", self.record_click) self.clickable_text_tag = "clickable_text_tag" self.text.bind("<ButtonRelease-1>", self.mouse_left_click) self.text.bind("<ButtonRelease-3>", self.mouse_right_click) self.text.bind("<Motion>", self.mouse_motion) self.last_click_index = "1.0" self.last_release_index = "1.0" self.command_list = [] # list of potential commands self.action = None # default command action self.default_action = None # default command action self.free_input = False # sets whether it's possible to input anything in the entry # basic text tags self.add_tag(GraphicalUserInterface.STRONG, font_weight="bold") self.add_tag(GraphicalUserInterface.ITALIC, font_weight="italic") self.add_tag(GraphicalUserInterface.HIGHLIGHT, background=self.highlight_background) self.text.tag_raise(SEL) # makes sure the selection is fisible
try: zk.delete(path, recursive=True) print(strs.SERVER_PREFIX + strs.MESSAGE_DELETE_SUCESS) except BadVersionError as _: print(strs.ERROR_PREFIX + strs.MESSAGE_BAD_VERSION) print(strs.SERVER_PREFIX + strs.MESSAGE_DELETE_FAILED) except NoNodeError as _: print(strs.ERROR_PREFIX + strs.MESSAGE_EXISTS_FALSE) print(strs.SERVER_PREFIX + strs.MESSAGE_DELETE_FAILED) except ZookeeperError as e: print(strs.ERROR_PREFIX + e.__str__()) print(strs.SERVER_PREFIX + strs.MESSAGE_DELETE_FAILED) #Helpers strs = Strings() reserved_words_commands = [ 'CREATE', 'READ', 'EXISTS', 'LIST', 'UPDATE', 'DELETE', 'DELETEC', 'QUIT' ] #Get data if len(sys.argv) == 3: SERVER_IP = sys.argv[1] SERVER_PORT = sys.argv[2] else: print(strs.ERROR_PREFIX + strs.MESSAGE_INCORRECT_USAGE_LINE_COMMAND) print(strs.SERVER_PREFIX + strs.MESSAGE_USAGE_LINE_COMMAND) #Stabilish Connection try: zk = KazooClient(hosts=SERVER_IP + ':' + SERVER_PORT)
def setUp(self): self.strings = Strings()
def page_not_found(e): return render_template('index.html', s=Strings(g.lang_code))
def __init__(self): self.model = Model() self.view = View() self.colors = Colors() self.strings = Strings()
def pull_lang_code(endpoint, values): if 'lang' in values: g.lang_code = values.pop('lang') else: g.lang_code = Strings.get_lang(request.headers.get('Accept-Language'))
from flask import Flask, request, jsonify from user import User from config import config from strings import Strings app = Flask(__name__) user = User() strings = Strings() @app.route('/health') def health(): return 'Python Flask server running on localhost:5000' @app.route('/user', methods=['GET']) def getUser(): firstName = request.args.get('firstName', '').strip() if firstName is "": return jsonify({'success': True}), 400 isFound, userData = user.get_user(firstName.strip()) if not isFound: return jsonify({'success': True}), 201 return jsonify(userData) @app.route('/user', methods=['POST']) def createUser():
def xmlbt_index(): return render_template('xmlbt_index.html', s=Strings(g.lang_code))
def pdfconv_index(): return render_template('pdfconv_index.html', s=Strings(g.lang_code))
def string_detection(neck): """ Detecting and separating strings into separate blocks by choosing numerous vertical slices in image We then look for a periodical pattern on each slice (ie strings detected), store points in between strings and connect them using a regression fitting function to separe each string :param neck: An Image object of the picture cropped around the horizontal neck :return strings, Image_string: either a string object which is a dict associating each string to a line (ie a tuple of points) delimiting the bottom of the string block // or directly an Image object with those lines displayed (illustration purpose) """ height = len(neck.image) width = len(neck.image[0]) neck_with_strings = np.zeros((height, width, 3), np.uint8) # 1. Detect strings with Hough transform and form an Image based on these edges = neck.edges_sobely() edges = threshold(edges, 127) lines = neck.lines_hough_transform( edges, 50, 20) # TODO: Calibrate params automatically if possible size = len(lines) for x in range(size): for x1, y1, x2, y2 in lines[x]: cv2.line(neck_with_strings, (x1, y1), (x2, y2), (255, 255, 255), 2) neck_str = Image(img=neck_with_strings) neck_str_gray = neck_str.gray # 2. Slice image vertically at different points and calculate gaps between strings at these slices slices = {} nb_slices = int(width / 50) for i in range(nb_slices): slices[(i + 1) * nb_slices] = [ ] # slices dict is {x_pixel_of_slice : [y_pixels_where_line_detected]} for index_line, line in enumerate(neck_str_gray): for index_pixel, pixel in enumerate(line): if pixel == 255 and index_pixel in slices: slices[index_pixel].append(index_line) slices_differences = { } # slices_differences dict is {x_pixel_of_slice : [gaps_between_detected_lines]} for k in slices.keys(): temp = [] n = 0 slices[k] = list(sorted(slices[k])) for p in range(len(slices[k]) - 1): temp.append(slices[k][p + 1] - slices[k][p]) if slices[k][p + 1] - slices[k][p] > 1: n += 1 slices_differences[k] = temp points = [] points_dict = {} for j in slices_differences.keys(): gaps = [g for g in slices_differences[j] if g > 1] points_dict[j] = [] if len(gaps) > 3: median_gap = median(gaps) for index, diff in enumerate(slices_differences[j]): if abs(diff - median_gap) < 4: points_dict[j].append( (j, slices[j][index] + int(median_gap / 2))) elif abs(diff / 2 - median_gap) < 4: points_dict[j].append( (j, slices[j][index] + int(median_gap / 2))) points_dict[j].append( (j, slices[j][index] + int(3 * median_gap / 2))) points.extend(points_dict[j]) '''for p in points: print(p) cv2.circle(neck.image, p, 3, (0, 255, 0), -1) plt.imshow(cv2.cvtColor(neck.image, cv2.COLOR_BGR2RGB)) plt.show()''' points_divided = [[] for i in range(5)] for s in points_dict.keys(): for i in range(5): try: # cv2.circle(neck.image, points_dict[s][i], 3, (255, 0, 0), -1) points_divided[i].append(points_dict[s][i]) except IndexError: pass # 3. Use fitLine function to form lines separating each string tuning = ["E", "A", "D", "G", "B", "E6"] strings = Strings(tuning) for i in range(5): cnt = np.array(points_divided[i]) [vx, vy, x, y] = cv2.fitLine(cnt, cv2.DIST_L12, 0, 0.01, 0.01) # best distType found was DIST_L12 left_extreme = int((-x * vy / vx) + y) right_extreme = int(((width - x) * vy / vx) + y) strings.separating_lines[tuning[i]] = [(width - 1, right_extreme), (0, left_extreme)] cv2.line(neck.image, (width - 1, right_extreme), (0, left_extreme), (0, 0, 255), 2) return strings, Image(img=neck.image)
class BaseState(object): HEADERS = { "Content-Type": "application/json" } # This variable allows to ignore `entry()` when needed has_entry = True # @Important: instantiate important classes tr = Translator() db = Database() nlu = NLUWorker(tr) STRINGS = Strings(tr, db) files = FILENAMES # Media path and folder media_folder = "media" media_path = os.path.join(ROOT_PATH, media_folder) if not os.path.exists(media_path): os.mkdir(media_path) # Prepare state def __init__(self): # Keeps list of tasks self.tasks = list() # Keeps execution queue self.execution_queue = list() # Create language variable self.__language = None self.strings = None def set_language(self, value: str): """ This method sets language to a current state If language is None - base language version is english Args: value (str): language code of the user's country """ self.__language = value or "en" self.strings = StringAccessor(self.__language, self.STRINGS) async def wrapped_entry(self, context: Context, user: User): # Set language self.set_language(user['language']) # Wrap base method to avoid breaking server try: # Execute state method status = await self.entry(context, user, self.db) except Exception as e: # Do not commit to database if something went wrong status = OK(commit=False) # Log exception logging.exception(e) # Commit changes to database if status.commit: await self.db.commit_user(user=user) # @Important: Fulfill text promises if self.strings.promises: await self.strings.fill_promises() # @Important: Since we call this always, check if # @Important: the call is actually needed if self.tasks: # @Important: collect all requests _results = await self.collect() # @Important: Execute all queued jobs if self.execution_queue: await self.execute_tasks() return status async def wrapped_process(self, context: Context, user: User): # Set language self.set_language(user['language']) # Wrap base method to avoid breaking server try: # Execute state method status = await self.process(context, user, self.db) except Exception as e: # Do not commit to database if something went wrong status = OK(commit=False) # Log exception logging.exception(e) # Commit changes to database if status.commit: await self.db.commit_user(user=user) # @Important: Fulfill text promises if self.strings.promises: await self.strings.fill_promises() # @Important: Since we call this always, check if # @Important: the call is actually needed if self.tasks: # @Important: collect all requests await self.collect() # @Important: Execute all queued jobs if self.execution_queue: await self.execute_tasks() return status # Actual state method to be written for the state async def entry(self, context: Context, user: User, db): return OK # Actual state method to be written for the state async def process(self, context: Context, user: User, db): return OK def parse_button(self, raw_text: str, truncated=False) -> Button: btn = Button(raw_text) lang_obj = self.STRINGS.cache.get(self.__language) if lang_obj is not None: if not truncated: for key, value in lang_obj.items(): if value == raw_text: btn.set_key(key) break else: for key, value in lang_obj.items(): if len(value) > 20 and value[:20] == raw_text[:20]: btn.set_key(key) break elif value == raw_text: btn.set_key(key) break return btn # @Important: 1) find better way with database # @Important: 2) What if we do it in non blocking asyncio.create_task (?) # @Important: But on the other hand, we can't relay on the file status # @Important: for example if next call needs to upload it somewhere # @Important: If you deal with reliability and consistency - great optimisation async def download_by_url(self, url, *folders, filename): # Make sure file exists if not self.exists(*folders): # Create folder on the path os.mkdir(os.path.join(self.media_path, *folders)) # Full file path with filename filepath = os.path.join(self.media_path, *folders, filename) # Initiate aiohttp sessions, get file async with ClientSession() as session: async with session.get(url) as response: # Open file with aiofiles and start steaming bytes, write to the file logging.debug(f"Downloading file: {url} to {filepath}") async with aiofiles.open(filepath, 'wb') as f: async for chunk in response.content.iter_any(): await f.write(chunk) logging.debug(f"Finished download [{filepath}]") return filepath # @Important: check if downloaded file exist def exists(self, *args): return os.path.exists(os.path.join(self.media_path, *args)) # @Important: high level access to translation module # @Important: note, though, that we shouldn't abuse translation api # @Important: because a) it's not good enough, b) it takes time to make # @Important: a call to the google cloud api async def translate(self, text: str, target: str) -> str: return await self.tr.translate_text(text, target) # Sugar # @Important: command to actually send all collected requests from `process` or `entry` async def collect(self): results = list() async with ClientSession(json_serialize=lambda o: json.dumps(o, cls=PromisesEncoder)) as session: # @Important: Since asyncio.gather order is not preserved, we don't want to run them concurrently # tasks = [self._send(task, session) for task in self.tasks[id(context)]] # group = asyncio.gather(*tasks) # results = await group # return results for each_task in self.tasks: res = await self._send(each_task, session) results.append(res) return results # @Important: Real send method, takes SenderTask as argument async def _send(self, task: SenderTask, session: ClientSession): # Takes instance data holder object with the name from the tokens storage, extracts url url = tokens[task.user['via_instance']].url # Unpack context, set headers (content-type: json) async with session.post(url, json=task.context, headers=self.HEADERS ) as resp: # If reached server - log response if resp.status == 200: pass # [DEBUG] #result = await resp.json() #if result: # logging.info(f"Sending task status: {result}") # return result #else: # logging.info(f"Sending task status: No result") # Otherwise - log error else: logging.error(f"[ERROR]: Sending task (user={task.user}, context={task.context}) status {await resp.text()}") # @Important: `send` METHOD THAT ALLOWS TO SEND PAYLOAD TO THE USER def send(self, to_user: User, context: Context): # @Important: [Explanation to the code below]: # @Important: maybe add some queue of coroutines and dispatch them all when handler return status (?) # @Important: or just dispatch them via asyncio.create_task so it will be more efficient (?) # @Important: reasoning: # @Important: simple way: server -> request1 -> status1 -> request2 -> status2 -> request3 -> status3 # @Important: this way: server -> gather(request1, request2, request3) -> log(status1, status2, status3) # @Important: The easy way to add files from files.json if isinstance(context['request']['message']['text'], TextPromise): # Find according key for files from TextPromise files = self.files.get(context['request']['message']['text'].key, list()) #logging.info(files) context['request']['file'] = [{"payload": _file} for _file in files] context['request']['has_file'] = bool(files) context['request']['has_image'] = bool(files) # [DEBUG] # logging.info(context['request']['message']['text'].key) else: # [DEBUG] pass # logging.info(context['request']['message']['text']) self.tasks.append(SenderTask(to_user, copy.deepcopy(context.__dict__['request']))) async def execute_tasks(self): results = await asyncio.gather( *[exec_task.func(*exec_task.args, **exec_task.kwargs) for exec_task in self.execution_queue] ) return results def create_task(self, func, *args, **kwargs): self.execution_queue.append(ExecutionTask(func, args, kwargs))