{"id":25300116,"url":"https://github.com/deftio/fifostr","last_synced_at":"2025-07-04T11:38:37.135Z","repository":{"id":47979731,"uuid":"63127553","full_name":"deftio/fifostr","owner":"deftio","description":"python mutable string class with streaming pattern recognition parser and FIFO support","archived":false,"fork":false,"pushed_at":"2021-08-15T14:44:56.000Z","size":164,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-16T16:48:49.123Z","etag":null,"topics":["deque","fifo-queue","mutable-python-string","parser","python","regex","streaming-parser"],"latest_commit_sha":null,"homepage":"https://deftio.com/fifostr","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/deftio.png","metadata":{"files":{"readme":"README-content.html","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-07-12T04:56:11.000Z","updated_at":"2024-04-01T20:30:59.000Z","dependencies_parsed_at":"2022-08-12T15:50:25.466Z","dependency_job_id":null,"html_url":"https://github.com/deftio/fifostr","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deftio%2Ffifostr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deftio%2Ffifostr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deftio%2Ffifostr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deftio%2Ffifostr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/deftio","download_url":"https://codeload.github.com/deftio/fifostr/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247569130,"owners_count":20959758,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deque","fifo-queue","mutable-python-string","parser","python","regex","streaming-parser"],"created_at":"2025-02-13T05:38:27.453Z","updated_at":"2025-04-06T23:40:39.212Z","avatar_url":"https://github.com/deftio.png","language":"Python","readme":"\u003cp\u003e\u003ca href=\"https://pypi.org/project/FIFOStr/\"\u003e\u003cimg src=\"https://img.shields.io/pypi/v/fifostr.svg\" alt=\"PyPi version\" /\u003e\u003c/a\u003e \u003ca href=\"https://travis-ci.com/deftio/fifostr\"\u003e\u003cimg src=\"https://travis-ci.com/deftio/fifostr.svg?branch=master\" alt=\"Build Status\" /\u003e\u003c/a\u003e \u003ca href=\"https://coveralls.io/github/deftio/fifostr?branch=master\"\u003e\u003cimg src=\"https://coveralls.io/repos/github/deftio/fifostr/badge.svg?branch=master\" alt=\"Coverage Status\" /\u003e\u003c/a\u003e \u003ca href=\"https://opensource.org/licenses/BSD-2-Clause\"\u003e\u003cimg src=\"https://img.shields.io/badge/License-BSD%202--Clause-blue.svg\" alt=\"License\" /\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"fifostr.py\"\u003efifostr.py\u003c/h1\u003e\n\u003cp\u003eFIFOStr - A python language string library designed to look for patterns in a stream, such as serial connection or look back parser. FIFOStr works by allowing character(s) to be inserted in to a FIFOstr object which is treated as FIFO (First-In-First-Out) buffer. The FIFOstr object can be set to a fixed size so that when a new character is inserted the last character is removed.\u003c/p\u003e\n\u003cp\u003eTrigger patterns (either strings, regular experssions, or customer parsers written in Python) can be attached to a FIFOstr object. If that pattern is deteced in a string, a callback function will is called to trigger an action. There is no limit to the number of patterns that can be deteted and each pattern can have a separate callback.\u003c/p\u003e\n\u003cp\u003eSince a FIFOstr is a fixed length buffer it can be attached to any stream with predictable resource consumption. FIFOstr also supports mutable character injection / mutable string support (used to inject / to test patterns).\u003c/p\u003e\n\u003cp\u003eExample code and a full test suite with CI are provided. See coverage and test section below.\u003c/p\u003e\n\u003cp\u003eLogically FIFOstr works as follows:\u003c/p\u003e\n\u003cdiv class=\"sourceCode\"\u003e\u003cpre class=\"sourceCode python\"\u003e\u003ccode class=\"sourceCode python\"\u003e\u003cspan class=\"im\"\u003efrom\u003c/span\u003e fifostr \u003cspan class=\"im\"\u003eimport\u003c/span\u003e FIFOStr\n\n\u003cspan class=\"co\"\u003e#initialize from a given string\u003c/span\u003e\nmyString \u003cspan class=\"op\"\u003e=\u003c/span\u003e FIFOStr(\u003cspan class=\"st\"\u003e\u0026quot;this is a test\u0026quot;\u003c/span\u003e) \u003cspan class=\"co\"\u003e# initialize with a string\u003c/span\u003e\n\u003cspan class=\"bu\"\u003elen\u003c/span\u003e(myString) \u003cspan class=\"op\"\u003e==\u003c/span\u003e \u003cspan class=\"dv\"\u003e14\u003c/span\u003e \u003cspan class=\"co\"\u003e#true\u003c/span\u003e\n\n\u003cspan class=\"co\"\u003e# The FIFOStr function head( int N) returns the the first N characters\u003c/span\u003e\nmyString.head(\u003cspan class=\"dv\"\u003e4\u003c/span\u003e) \u003cspan class=\"op\"\u003e==\u003c/span\u003e \u003cspan class=\"st\"\u003e\u0026quot;this\u0026quot;\u003c/span\u003e  \u003cspan class=\"co\"\u003e#true\u003c/span\u003e\n\nmyString\u003cspan class=\"op\"\u003e+=\u003c/span\u003e \u003cspan class=\"st\"\u003e\u0026quot; more\u0026quot;\u003c/span\u003e \u003cspan class=\"co\"\u003e# this addes the string \u0026quot; more\u0026quot; to myString, each character is fed in and the last character in the FIFOstr is removed.\u003c/span\u003e\n\n\u003cspan class=\"co\"\u003e#initialize with max fixed length\u003c/span\u003e\nmyString.head(\u003cspan class=\"dv\"\u003e4\u003c/span\u003e) \u003cspan class=\"op\"\u003e==\u003c/span\u003e \u003cspan class=\"st\"\u003e\u0026quot;is a\u0026quot;\u003c/span\u003e  \u003cspan class=\"co\"\u003e#true because the string is also a true FIFO and keeps fixed length.  Look at example below for more on pattern matching (and multiple pattern matching for more details)\u003c/span\u003e\n\nmyString \u003cspan class=\"op\"\u003e=\u003c/span\u003e FIFOStr(\u003cspan class=\"dv\"\u003e10\u003c/span\u003e)  \u003cspan class=\"co\"\u003e# creates a blank FIFOStr max length FIFOStr of 10 chars\u003c/span\u003e\n\u003cspan class=\"bu\"\u003elen\u003c/span\u003e(myString)  \u003cspan class=\"co\"\u003e# returns 0, there is no data in FIFOstr yet\u003c/span\u003e\nmyString \u003cspan class=\"op\"\u003e+=\u003c/span\u003e \u003cspan class=\"st\"\u003e\u0026quot;This\u0026quot;\u003c/span\u003e\n\u003cspan class=\"bu\"\u003elen\u003c/span\u003e(myString) \u003cspan class=\"op\"\u003e==\u003c/span\u003e \u003cspan class=\"dv\"\u003e4\u003c/span\u003e  \u003cspan class=\"co\"\u003e# true\u003c/span\u003e\nmyString \u003cspan class=\"op\"\u003e+=\u003c/span\u003e \u003cspan class=\"st\"\u003e\u0026quot; is more stuff\u0026quot;\u003c/span\u003e  \u003cspan class=\"co\"\u003e# add characters to end of string\u003c/span\u003e\n\u003cspan class=\"bu\"\u003elen\u003c/span\u003e(myString) \u003cspan class=\"op\"\u003e==\u003c/span\u003e \u003cspan class=\"dv\"\u003e10\u003c/span\u003e  \u003cspan class=\"co\"\u003e#true\u003c/span\u003e\nmyString \u003cspan class=\"op\"\u003e==\u003c/span\u003e \u003cspan class=\"st\"\u003e\u0026quot;more stuff\u0026quot;\u003c/span\u003e  \u003cspan class=\"co\"\u003e# true, string is at max len of 10 chars\u003c/span\u003e\n\n\u003cspan class=\"co\"\u003e#mutable support\u003c/span\u003e\nmyString[\u003cspan class=\"dv\"\u003e2\u003c/span\u003e] \u003cspan class=\"op\"\u003e==\u003c/span\u003e \u003cspan class=\"st\"\u003e\u0026#39;d\u0026#39;\u003c/span\u003e \u003cspan class=\"co\"\u003e# in place modification (mutable string)\u003c/span\u003e\nmyString \u003cspan class=\"op\"\u003e==\u003c/span\u003e \u003cspan class=\"st\"\u003e\u0026quot;mode stuff\u0026quot;\u003c/span\u003e \u003cspan class=\"co\"\u003e# string position[2] is changed \u003c/span\u003e\n\n\u003cspan class=\"co\"\u003e#For pattern matching \u0026amp; triggers see examples section.\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp\u003eOriginally a lighter version of this was used in a python serial terminal program which allowed the serial terminal to parse commands sent/received by both sides.\u003c/p\u003e\n\u003ch2 id=\"pattern-triggering-features\"\u003ePattern Triggering Features\u003c/h2\u003e\n\u003cp\u003eBuilt-in pattern matching and triggering: simply add / remove patterns which then call a callback function (E.g. if the pattern is \u0026quot;seen\u0026quot; then trigger the function). Patterns can be strings, regexes or user-supplied-functions (parsers written in python). A pattern consists of:\u003cbr /\u003e\n* pattern: string \u003cem\u003eor\u003c/em\u003e compiled regex \u003cem\u003eor\u003c/em\u003e user-supplied-parser-function\u003cbr /\u003e\n* label: user supplied 'name' for this pattern\u003cbr /\u003e\n* start index : position in fifostr to begin pattern match. default is 0 (also accepts the character '^' as start anchor for those familiar with regexes) * stop index : position in fifostr to end pattern match. default is end of fifostr. the letter '$' has special meaning as end of string no matter the length (again regex) * callback_fn : called if pattern is found, fifostr(start:end) and the label are passed to the callback function (callback('thematchingstring','label')) * active : default is True, sets whether this pattern should be actively looked for\u003cbr /\u003e\n* mutable string support for changing the contents middle position characters to look at callback responses.\u003c/p\u003e\n\u003ch3 id=\"installation\"\u003eInstallation\u003c/h3\u003e\n\u003cpre\u003e\u003ccode\u003epip install fifostr # or just pull fifostr.py from the source repository and put in your source path  \u003c/code\u003e\u003c/pre\u003e\n\u003ch3 id=\"original-usage\"\u003eOriginal Usage\u003c/h3\u003e\n\u003cp\u003eOriginally part of a terminal program called 'dioterm' (albeit in much more compact form), this library was used used to 'listen' to traffic in either direction on a serial port. When certain patterns were found such as a command sent from the host or a special piece of data from the embedded microntroller client, fifostr would trigger a callback to do something. This was very useful when sequences of commands had to be set up between the host and client. Many of these sequences where conditional based on what either the host or client sent resulting in many variations of sequence-test cases, especially if this results in the host then having to make some other call to an unrelated process or hardware to reply correctly.\u003c/p\u003e\n\u003ch3 id=\"functionality\"\u003eFunctionality\u003c/h3\u003e\n\u003cp\u003eFIFOStr is a string which is (derived from deque) with these properties:\u003cbr /\u003e\n* add/remove chars or strings at either end\u003cbr /\u003e\n* mutable (can set a char to any value like an array with []) * use slices, lists, or tuples to retrieve members (just like a real str object)\u003cbr /\u003e\n* get head/tail (returns as a str)\u003cbr /\u003e\n* match head/tail --\u0026gt; match a supplied string to either the head or tail\u003cbr /\u003e\n* use patterns to trigger callbacks --\u0026gt; pattern can be string | regex | user_supplied_parser any of which triggers user supplied callback_fn\u003cbr /\u003e\n* all patterns can look at either the whole fifostr or any subset e.g. addPattern(\u0026quot;foo\u0026quot;,myCallback,2,5,\u0026quot;bar\u0026quot;) --\u0026gt; only looks for \u0026quot;foo\u0026quot; between positions 2 and 5 in the fifostr and will call myCallback with (\u0026quot;foo\u0026quot;,\u0026quot;bar\u0026quot;) if found * all patterns have optional label which can be used for logging purposes (eg. when pattern found, in addition to callback, emit label)\u003cbr /\u003e\n* user supplied callback_fn is called with both the string-match section and the label\u003cbr /\u003e\n* patterns can be added/deleted from the list of patterns \u0026quot;watching\u0026quot; the fifostr content * all (active) patterns are always matched. fifostr matches multiple different patterns over the same string.\u003cbr /\u003e\n* clear all patterns --\u0026gt; removes patterns from processing\u003cbr /\u003e\n* get/setPattern Active/Inactive --\u0026gt; allows a stored pattern to set on or off\u003cbr /\u003e\n* Python 2.7+, Python 3+ support, derived from built-in deque package\u003cbr /\u003e\n* 100% test coverage in both 2.7 and 3.x\u003c/p\u003e\n\u003ch3 id=\"usage-example\"\u003eUsage example\u003c/h3\u003e\n\u003cp\u003eSee example.py to run in tests dir -- same examples as here but more comments, more use cases\u003c/p\u003e\n\u003cdiv class=\"sourceCode\"\u003e\u003cpre class=\"sourceCode python\"\u003e\u003ccode class=\"sourceCode python\"\u003e\u003cspan class=\"im\"\u003efrom\u003c/span\u003e fifostr \u003cspan class=\"im\"\u003eimport\u003c/span\u003e FIFOStr\n\u003cspan class=\"kw\"\u003edef\u003c/span\u003e main():\n    myFifoStr\u003cspan class=\"op\"\u003e=\u003c/span\u003eFIFOStr(\u003cspan class=\"dv\"\u003e5\u003c/span\u003e) \u003cspan class=\"co\"\u003e#make a fifostr of length 5 (for unlimited length omit number)\u003c/span\u003e\n    myFifoStr\u003cspan class=\"op\"\u003e+=\u003c/span\u003e\u003cspan class=\"st\"\u003e\u0026#39;1234567\u0026#39;\u003c/span\u003e \u003cspan class=\"co\"\u003e#adds 1234567 to fifostr ... but len of fifostr is 5\u003c/span\u003e\n                         \u003cspan class=\"co\"\u003e# so only 34567 is retained\u003c/span\u003e\n   \n    \u003cspan class=\"bu\"\u003eprint\u003c/span\u003e \u003cspan class=\"st\"\u003e\u0026quot;myFifoStr.head(3)= \u0026quot;\u003c/span\u003e,myFifoStr.head(\u003cspan class=\"dv\"\u003e3\u003c/span\u003e) \u003cspan class=\"co\"\u003e#shows 345\u003c/span\u003e\n    \u003cspan class=\"bu\"\u003eprint\u003c/span\u003e \u003cspan class=\"st\"\u003e\u0026quot;myFifoStr.tail(4)= \u0026quot;\u003c/span\u003e,myFifoStr.tail(\u003cspan class=\"dv\"\u003e4\u003c/span\u003e) \u003cspan class=\"co\"\u003e#shows 4567\u003c/span\u003e\n\n    \u003cspan class=\"co\"\u003e# the eqhead and eqtail functions allow string compares against\u003c/span\u003e\n    \u003cspan class=\"co\"\u003e# the head or the tail\u003c/span\u003e\n\n    myFifoStr.eqhead(\u003cspan class=\"st\"\u003e\u0026quot;3456\u0026quot;\u003c/span\u003e)    \u003cspan class=\"co\"\u003e#True\u003c/span\u003e\n    myFifoStr.eqhead(\u003cspan class=\"st\"\u003e\u0026quot;567\u0026quot;\u003c/span\u003e)     \u003cspan class=\"co\"\u003e#False\u003c/span\u003e\n    myFifoStr.eqtail(\u003cspan class=\"st\"\u003e\u0026quot;4567\u0026quot;\u003c/span\u003e)    \u003cspan class=\"co\"\u003e#True\u003c/span\u003e\n    myFifoStr.eqtail(\u003cspan class=\"st\"\u003e\u0026quot;abc\u0026quot;\u003c/span\u003e)     \u003cspan class=\"co\"\u003e#False\u003c/span\u003e\n\n    \u003cspan class=\"co\"\u003e#fifostr.testPattern() allows you to test if the pattern is present in the fifostr object\u003c/span\u003e\n    \u003cspan class=\"co\"\u003e#test a  string pattern directly\u003c/span\u003e\n    myFifoStr.testPattern(\u003cspan class=\"st\"\u003e\u0026#39;67890\u0026#39;\u003c/span\u003e) \u003cspan class=\"co\"\u003e#False\u003c/span\u003e\n    \n    \u003cspan class=\"co\"\u003e#test a regex pattern directly.  to do this pass any valid regex in compiled form\u003c/span\u003e\n    r1\u003cspan class=\"op\"\u003e=\u003c/span\u003ere.\u003cspan class=\"bu\"\u003ecompile\u003c/span\u003e(\u003cspan class=\"st\"\u003e\u0026quot;[0-9]+\u0026quot;\u003c/span\u003e)\n    myFifoStr.testPattern(r1)   \u003cspan class=\"co\"\u003e#True\u003c/span\u003e\n\n    r2\u003cspan class=\"op\"\u003e=\u003c/span\u003ere.\u003cspan class=\"bu\"\u003ecompile\u003c/span\u003e(\u003cspan class=\"st\"\u003e\u0026quot;[a-z]+\u0026quot;\u003c/span\u003e)\n    myFifoStr.testPattern(r2)   \u003cspan class=\"co\"\u003e#False\u003c/span\u003e\n\n    \u003cspan class=\"co\"\u003e#more generally we can add (and remove) patterns which will scan and trigger a call back everytime the fifostr \u003c/span\u003e\n    \u003cspan class=\"co\"\u003e#internal content changes (whether adding or deleting chars from either end or even rotating/reversing the fifstr object)\u003c/span\u003e\n\n    \u003cspan class=\"co\"\u003e#adding patterns\u003c/span\u003e\n    p1 \u003cspan class=\"op\"\u003e=\u003c/span\u003e myFifoStr.addPattern(\u003cspan class=\"st\"\u003e\u0026quot;234\u0026quot;\u003c/span\u003e,logf,label\u003cspan class=\"op\"\u003e=\u003c/span\u003e\u003cspan class=\"st\"\u003e\u0026quot;234 was here\u0026quot;\u003c/span\u003e) \u003cspan class=\"co\"\u003e#integer index returned managing pattern \u003c/span\u003e\n    p2 \u003cspan class=\"op\"\u003e=\u003c/span\u003e myFifoStr.addPattern(\u003cspan class=\"st\"\u003e\u0026quot;67890\u0026quot;\u003c/span\u003e,logf,label\u003cspan class=\"op\"\u003e=\u003c/span\u003e\u003cspan class=\"st\"\u003e\u0026quot;67890 detected\u0026quot;\u003c/span\u003e)\n    p3 \u003cspan class=\"op\"\u003e=\u003c/span\u003e myFifoStr.addPattern(r1,logf,label\u003cspan class=\"op\"\u003e=\u003c/span\u003e\u003cspan class=\"st\"\u003e\u0026quot;r1 detected\u0026quot;\u003c/span\u003e)\n    myFifoStr.addPattern(r2,logf,label\u003cspan class=\"op\"\u003e=\u003c/span\u003e\u003cspan class=\"st\"\u003e\u0026quot;r2 hit\u0026quot;\u003c/span\u003e)\n    myFifoStr.addPattern(f1,logf,label\u003cspan class=\"op\"\u003e=\u003c/span\u003e\u003cspan class=\"st\"\u003e\u0026quot;f1 hit\u0026quot;\u003c/span\u003e)   \n    myFifoStr.addPattern(f2,logf,label\u003cspan class=\"op\"\u003e=\u003c/span\u003e\u003cspan class=\"st\"\u003e\u0026quot;f2 hit\u0026quot;\u003c/span\u003e)    \n\n    \u003cspan class=\"co\"\u003e#patterns can be set active/inactive via pattern management fns \u003c/span\u003e\n    myFifoStr.setPatternActiveState(p1,\u003cspan class=\"va\"\u003eFalse\u003c/span\u003e) \u003cspan class=\"co\"\u003e#based on index returned from addPattern\u003c/span\u003e\n\n    \u003cspan class=\"co\"\u003e#now show searching for stored pattern matchers in the pattern dict\u003c/span\u003e\n    \u003cspan class=\"co\"\u003e#this is not searching the fifo-string itself, just the stored patterns that we have entered\u003c/span\u003e\n    \u003cspan class=\"bu\"\u003eprint\u003c/span\u003e(\u003cspan class=\"st\"\u003e\u0026quot;find pattern by label \u0026#39;foo\u0026#39;:\u0026quot;\u003c/span\u003e,myFifoStr.findPatternByLabel(\u003cspan class=\"st\"\u003e\u0026quot;foo\u0026quot;\u003c/span\u003e)) \u003cspan class=\"co\"\u003e#no matches returns empty list\u003c/span\u003e\n    \u003cspan class=\"bu\"\u003eprint\u003c/span\u003e(\u003cspan class=\"st\"\u003e\u0026quot;find pattern by label \u0026#39;234 hit\u0026#39;:\u0026quot;\u003c/span\u003e,myFifoStr.findPatternByLabel(\u003cspan class=\"st\"\u003e\u0026quot;234 hit\u0026quot;\u003c/span\u003e)) \u003cspan class=\"co\"\u003e#shows match\u003c/span\u003e\n    \u003cspan class=\"bu\"\u003eprint\u003c/span\u003e(\u003cspan class=\"st\"\u003e\u0026quot;find pattern by label using regex \u0026#39;[rf][0-9]\u0026#39;:\u0026quot;\u003c/span\u003e)\n    pp.pprint(myFifoStr.findPatternByLabel(re.\u003cspan class=\"bu\"\u003ecompile\u003c/span\u003e(\u003cspan class=\"st\"\u003e\u0026quot;[rf][0-9]\u0026quot;\u003c/span\u003e)))\n\n    \u003cspan class=\"co\"\u003e#and finally demonstrate that patterns auto-trigger when items inserted in fifostr .. which afterall\u003c/span\u003e\n    \u003cspan class=\"co\"\u003e#is the point of the whole thing.. ;)\u003c/span\u003e\n    \u003cspan class=\"bu\"\u003eprint\u003c/span\u003e(\u003cspan class=\"st\"\u003e\u0026quot;\u003c/span\u003e\u003cspan class=\"ch\"\u003e\\n\u003c/span\u003e\u003cspan class=\"st\"\u003e fifo operations ============\u0026quot;\u003c/span\u003e)\n    \u003cspan class=\"cf\"\u003efor\u003c/span\u003e c \u003cspan class=\"kw\"\u003ein\u003c/span\u003e \u003cspan class=\"st\"\u003e\u0026#39;01234567890abcdefghijklmnop\u0026#39;\u003c/span\u003e:  \u003cspan class=\"co\"\u003e#show using inc which accomplishes same thing\u003c/span\u003e\n        myFifoStr \u003cspan class=\"op\"\u003e+=\u003c/span\u003e c\n\n    myFifoStr\u003cspan class=\"op\"\u003e+=\u003c/span\u003e \u003cspan class=\"st\"\u003e\u0026#39;abcdefghi\u0026#39;\u003c/span\u003e\n    \u003cspan class=\"bu\"\u003eprint\u003c/span\u003e (myFifoStr.\u003cspan class=\"bu\"\u003eall\u003c/span\u003e())\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003ch3 id=\"notes\"\u003eNotes\u003c/h3\u003e\n\u003cp\u003eFIFOstr is not meant replacement for a compiler/parser front end though it can be used as complex tokenizer. Internally just iterates over stored patterns every time something is added to the fifostr object. If you do have a parser you wish to be called then just add it as a callback function so that every time the fifostr is updated with a char(s) it will call your parser to do the work. Your parser must return a boolean result if you wish to use the callback based triggering. Multiple custom parsers can be run in along with static string patterns or regexes.\u003c/p\u003e\n\u003cdiv class=\"sourceCode\"\u003e\u003cpre class=\"sourceCode python\"\u003e\u003ccode class=\"sourceCode python\"\u003e\u003cspan class=\"co\"\u003e#let your own parser do the work  \u003c/span\u003e\n    myFifo \u003cspan class=\"op\"\u003e=\u003c/span\u003e fifostr(\u003cspan class=\"dv\"\u003e20\u003c/span\u003e)  \u003cspan class=\"co\"\u003e# make a 20 char fifostr\u003c/span\u003e\n    myFifo.addPattern(myParser,myCallbk) \u003cspan class=\"co\"\u003e#myParser passed entire fifostr (as str) when char(s) added\u003c/span\u003e\n    myFifo.addPattern(myParser,myCallbk2,\u003cspan class=\"dv\"\u003e3\u003c/span\u003e,\u003cspan class=\"dv\"\u003e5\u003c/span\u003e) \u003cspan class=\"co\"\u003e#myParser passed fifostr btw (3,5).  My Parser must return True if match found for callback to be invoked\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003ch3 id=\"source-code\"\u003eSource code\u003c/h3\u003e\n\u003cp\u003eall source is at github:\u003cbr /\u003e\nhttps://github.com/deftio/fifostr\u003c/p\u003e\n\u003ch3 id=\"project-home\"\u003eProject Home\u003c/h3\u003e\n\u003cp\u003ehttps://deftio.com/fifostr\u003c/p\u003e\n\u003ch3 id=\"company-home\"\u003eCompany Home\u003c/h3\u003e\n\u003cp\u003edocs and other projects at\u003cbr /\u003e\nhttps://deftio.com/\u003c/p\u003e\n\u003ch3 id=\"tests-coverage\"\u003eTests \u0026amp; Coverage\u003c/h3\u003e\n\u003cp\u003efor quick usage see\u003cbr /\u003e\nsee \u003cstrong\u003emain\u003c/strong\u003e in example.py file\u003c/p\u003e\n\u003cp\u003efor test coverage look in the /tests directory\u003cbr /\u003e\nto run tests pytest needs to be installed.\u003c/p\u003e\n\u003ch4 id=\"on-ubuntu\"\u003eon Ubuntu\u003c/h4\u003e\n\u003cdiv class=\"sourceCode\"\u003e\u003cpre class=\"sourceCode bash\"\u003e\u003ccode class=\"sourceCode bash\"\u003e\u003cspan class=\"ex\"\u003epip\u003c/span\u003e install -U pytest pytest-cov \n\u003cspan class=\"ex\"\u003epip\u003c/span\u003e install coveralls   \u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp\u003enote: more info at pytest.org for installation on other OSes\u003c/p\u003e\n\u003cdiv class=\"sourceCode\"\u003e\u003cpre class=\"sourceCode bash\"\u003e\u003ccode class=\"sourceCode bash\"\u003e\u003cspan class=\"co\"\u003e# running basic tests\u003c/span\u003e\n\u003cspan class=\"bu\"\u003ecd\u003c/span\u003e tests\n\u003cspan class=\"ex\"\u003epytest\u003c/span\u003e  #or py.test \n\n\u003cspan class=\"co\"\u003e# coverage stats below\u003c/span\u003e\n\u003cspan class=\"ex\"\u003ecoverage\u003c/span\u003e run --source fifostr -m pytest \n\u003cspan class=\"ex\"\u003ecoverage\u003c/span\u003e report -m\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003ch3 id=\"generating-docs\"\u003eGenerating docs\u003c/h3\u003e\n\u003cp\u003eDocumenation is generated using pandoc and pydoc from the build scripts.\u003c/p\u003e\n\u003cdiv class=\"sourceCode\"\u003e\u003cpre class=\"sourceCode bash\"\u003e\u003ccode class=\"sourceCode bash\"\u003e\u003cspan class=\"fu\"\u003esudo\u003c/span\u003e apt-get install pandoc\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp\u003edocumentation is in /docs directory (generated by pydoc) to (re)generate the docs. cd to the docs directory. then type:\u003c/p\u003e\n\u003cdiv class=\"sourceCode\"\u003e\u003cpre class=\"sourceCode bash\"\u003e\u003ccode class=\"sourceCode bash\"\u003e\u003cspan class=\"ex\"\u003epydoc\u003c/span\u003e -w ../fifostr.py  \u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp\u003enote that as of this writing pydoc generates its output in the current directory and doesn't seem to be pipeable to another.\u003c/p\u003e\n\u003ch3 id=\"release-history\"\u003eRelease History\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e1.1.19 added sys.displayhook chaining for interactive mode display\u003c/li\u003e\n\u003cli\u003e1.1.18 added Str constructor\u003c/li\u003e\n\u003cli\u003e1.1.17 updated to support 3.9x\u003c/li\u003e\n\u003cli\u003e1.1.16 updated to support python 3.7 3.8 3.9 in tests\u003c/li\u003e\n\u003cli\u003e1.1.15 updated PyPi to use README.md instead of README.rst (no other changes)\u003c/li\u003e\n\u003cli\u003e1.1.10 Updated docs and related usage info for repo\u003c/li\u003e\n\u003cli\u003e1.1.9 rebuild for README.md to README.rst conversion using pandoc (no code changes) for PyPi\u003c/li\u003e\n\u003cli\u003e1.1.8 rebuild to make sure proper pkg loaded to PyPi (no code changes)\u003c/li\u003e\n\u003cli\u003e1.1.7 updated MANIFEST.in to use README.rst\u003c/li\u003e\n\u003cli\u003e1.1.6 added PyPi version badge in README.md\u003c/li\u003e\n\u003cli\u003e1.1.5 coverage to 100%, added badging, added README.rst\u003c/li\u003e\n\u003cli\u003e1.1.x changed class name from fifostr to FIFOStr to make PEP8 compliant. fixed bug in setup.py (package_dir)\u003c/li\u003e\n\u003cli\u003e1.0.x documentation clean up\u003c/li\u003e\n\u003cli\u003e1.0.0 Initial release\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"readme.md-vs-readme.rst\"\u003eREADME.md vs README.rst\u003c/h3\u003e\n\u003cp\u003eThe README.rst is generated from the README.md using pandoc but the content is identical. (used for PyPi in earlier releases)\u003c/p\u003e\n\u003ch3 id=\"license\"\u003eLicense\u003c/h3\u003e\n\u003cp\u003eSee LICENSE.txt file in this directory. The license is the OSI approved \u0026quot;FreeBSD\u0026quot; 2 clause license.\u003c/p\u003e\n\u003col start=\"3\" style=\"list-style-type: lower-alpha\"\u003e\n\u003cli\u003e2018 m a chatterjee\u003c/li\u003e\n\u003c/ol\u003e\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeftio%2Ffifostr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdeftio%2Ffifostr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeftio%2Ffifostr/lists"}