Re: [Twisted-Python] Embedding manhole interpreter into insults widget.

2014-08-07 Thread Maxim Lacrima
On 6 August 2014 22:48, Glyph Lefkowitz  wrote:

>
> Optimizing this will almost certainly involve patching Twisted.  Which you
> should definitely do :).
>
> The reason the entire screen is redrawn is that a *general* implementation
> of a widget, i.e. one that can be displayed anywhere on the terminal, you
> do just have to redraw the entire widget when certain things happen, like
> when the screen scrolls.  You can see this in other software by observing
> the fairly significant performance difference between a vertical split and
> a horizontal split in tmux.  Nothing to do with Twisted there, just a
> general limitation of terminals.
>

> The optimizations you could implement are one where inputting individual
> characters doesn't cause a full screen redraw, and avoiding a full screen
> redraw when scrolling if the edges of the widget touch the edges of the
> full terminal (setting up a scroll area for that case).
>

When manhole is used directly, then it is very responsive, and the
performance doesn't degrade with increase of screen size. It holds only
what user entered and writes the input line and command output directly to
its transport, without bothering itself with processing of the whole
screen. When I embed manhole into the widget like above, then the
performance suffers. I think this is due to `TerminalBuffer` having to hold
whole widget area (columns * rows) in memory, even if only a small portion
of it is actually occupied by user input and command output. Rendering the
whole buffer on each keystroke is slow. After experimenting a little bit, I
think optimizations that you described mostly apply to
`ManholeWidget.render` method, which shouldn't traverse the whole buffer on
each keystroke. Currently I don't see how this involves patching widget
implementation in Twisted. What is more important to me is that
`TerminalBuffer` implementation is slightly incomplete. I think it misses
color support, because I couldn't make it work with `ColoredManhole`.


>
> -glyph
>
> ___
> Twisted-Python mailing list
> Twisted-Python@twistedmatrix.com
> http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
>
>


-- 
Regards,
Maxim
___
Twisted-Python mailing list
Twisted-Python@twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python


Re: [Twisted-Python] Embedding manhole interpreter into insults widget.

2014-08-07 Thread exarkun

On 6 Aug, 06:14 pm, lacrima.ma...@gmail.com wrote:

Hello,

I have been trying to create a widget that encloses manhole 
interpreter.
Here is somewhat hacky implementation that I came up with at this 
moment:


Widgets and the manhole interpreter are implemented using two pretty 
distinct approaches.


As you've figured out, these approaches can be integrated (at least in 
one direction) using a terminal emulator - 
`twisted.conch.insults.helper.TerminalBuffer`.


However, `TerminalBuffer` is an extremely low quality terminal emulator. 
Among its many flaws is that it uses a number of incredibly inefficient 
implementations for common terminal operations (many of its other flaws 
are along the lines of "it has a bug in the implementation of X").


If I were going to create a manhole widget then I would do it "natively" 
- not by bridging the existing manhole protocol to the widget system 
with TerminalBuffer but by writing a new widget that does manhole stuff 
all by itself.


I suggest that you might want to pursue this approach instead of trying 
to optimize and fix bugs in TerminalBuffer.


Ultimately it would be nice if a widget-based manhole were *the* manhole 
and the current implementation went away.


However, that said, as far as I know, no vt-style terminals support 
efficient redrawing for the "vertically scroll one portion of the 
terminal separated from another portion by a vertical divider".


You will be able to avoid the redundant work of re-rendering the Python 
buffer representing the terminal state but you'll still have to re- 
transmit the bytes representing the entire terminal display to the 
terminal on each redraw - unless you avoid vertical dividers.


Jean-Paul

___
Twisted-Python mailing list
Twisted-Python@twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python


Re: [Twisted-Python] Is there pb documentation somewhere?

2014-08-07 Thread Daniel Sank
glyph,

> I really wish we would stop calling things "bad" and "good".

My wording of exarkun's wording. He gave a much more detailed description
of what he think's is "crazy" about pb.

> make your own decisions about how to write your own code.

Indeed, but gathering information from wiser folks is always a good idea,
and usually best done _often_ during development :)

> I'm happy to trade 2-for-1 - if you do two code reviews, I will regard it
as an immediate obligation for
> me to review a ticket you direct me to ;).

Deal. However, rather than direct your attention to tickets, at this stage
I would rather trade reviews for discussion. I'll do two reviews and then
post a few questions to this mailing list thread. Once I start actually
writing patches/new code we can trade reviews for attention to tickets. Ok?

> These would also be easier to land, and a couple of decades in open
source has taught me that nothing
> motivates development activity like successful development activity ;).

Indeed. There are one or two architectural issues I want to understand
before moving on to real coding. I will try to get through that asap by
reviewing tickets and trading for discussion of those architectural issues.

> Hopefully you can make sense out of the explanations above and your own
existing knowledge.
> Are there any other phases of the process which are confusing?

This all makes sense now. I hadn't understood the point of the cooker, but
now that you've explained it, I understand what's going on. I will
transform your mailing list explanation to documentation shortly.

Daniel
___
Twisted-Python mailing list
Twisted-Python@twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python


[Twisted-Python] pb.Copyable knowledge barrier

2014-08-07 Thread Kevin Mcintyre
goal: Give knowitall.py awareness of wordsmith.py addition.

to run
./library.sh # opens 7999 for remote_dictionary and remote_define methods
then both:
python knowitall.py
python wordsmith.py

library.sh due to main/jelly issues
from twisted.spread import pb

class UknownWordException(Exception):
pass

class UnknownDefinition(UknownWordException):
pass
# would like to remote define via error

class Dictionary():

def __init__(self, language, word=None, definition=None):
self.language = language
	self.words = {}
	if not word:
	word = language
	if not definition:
	definition = language + ' is a word worthy of a language'
	self.words[word] = set([definition])
	print self.words

def get_language(self):
return self.language

def lookup_word(self, word, definition = None):
	print 'lookup_word', self.words
try:
	return self.words[word]
except:
	if definition:
	raise UknownWordException(word)
	else:
	raise UnknownDefinition(word, definition)

class CopyDictionary(Dictionary, pb.Copyable):

def getStateToCopy(self):
print 'state getting copied', self.language
return self.language, self.words

class DictionaryEditor(pb.Referenceable):

def remote_word_definition(self, lanague, word, definition):
pass

class RemoteDictionary(pb.RemoteCopy, Dictionary):

def setCopyableState(self, state):
print 'remote state receives copy', state
self.language = state[0]
self.words = state[1]

class Library(pb.Root):

dictionaries = []

def remote_define(self, language, word, definition):
	dictionary = self.remote_dictionary(language, word, definition)	
	try:
	definition_set = dictionary.lookup_word(word, definition)
	print 'got definition_set', definition_set
	if definition not in definition_set:
		print 'new definition'
		definition_set.add(definition)
	else:
		print 'existing definition'
	except Exception as e:
	print e
	print 'new word'
	dictionary.words[word] = set([definition])
	return dictionary.words
		

def remote_dictionary(self, language, word = None, definition = None):
for d in Library.dictionaries:
if d.get_language() == language:
print 'remote'
return d
print 'create copyable version'
dictionary = CopyDictionary(language, word, definition)
Library.dictionaries.append(dictionary)
return dictionary
from twisted.spread import pb
from example import CopyDictionary, RemoteDictionary
from twisted.internet import reactor
from twisted.internet import defer

factory = pb.PBClientFactory()
reactor.connectTCP("localhost", 7999, factory)

pb.setUnjellyableForClass(CopyDictionary, RemoteDictionary)

def use_dictionary(dictionary):
for w in dictionary.words.keys():
	for d in dictionary.words[w]:
	print w, d
reactor.callLater(10, use_dictionary, dictionary)

def goto_library():
return factory.getRootObject()

import sys
language = 'english'
if len(sys.argv) > 1:
language = sys.argv[1]

def test():
d = goto_library()
d.addCallback(lambda root: root.callRemote('dictionary', language))
d.addCallback(use_dictionary)
return d

reactor.callWhenRunning(test)
reactor.run()



library.sh
Description: Bourne shell script
from twisted.spread import pb
from twisted.internet import reactor
from twisted.internet import defer

factory = pb.PBClientFactory()
reactor.connectTCP("localhost", 7999, factory)

def goto_library():
return factory.getRootObject()

def define_result(ans, language, word, definition):
# audit submission later
print ans
reactor.stop()

language = 'english'
word = language
definition = word + ' is part of ' + language

import sys 
if len(sys.argv) > 1:
language = sys.argv[1]
if len(sys.argv) > 2:
word = sys.argv[2]
if len(sys.argv) > 3:
definition = sys.argv[3]

def test():
d = goto_library()
d.addCallback(lambda root: root.callRemote('define', language, word, definition))
d.addCallback(define_result, language, word, definition)
return d

reactor.callWhenRunning(test)
reactor.run()

___
Twisted-Python mailing list
Twisted-Python@twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python


Re: [Twisted-Python] pb.Copyable knowledge barrier

2014-08-07 Thread Kevin Mcintyre
wordsmith argument order issues re-take.

Cheers,
Kevin


On Thu, Aug 7, 2014 at 11:29 PM, Kevin Mcintyre  wrote:

> goal: Give knowitall.py awareness of wordsmith.py addition.
>
> to run
> ./library.sh # opens 7999 for remote_dictionary and remote_define methods
> then both:
> python knowitall.py
> python wordsmith.py
>
> library.sh due to main/jelly issues
>
>
from twisted.spread import pb

class UknownWordException(Exception):
pass

class UnknownDefinition(UknownWordException):
pass
# would like to remote define via error

class Dictionary():

def __init__(self, language, word=None, definition=None):
self.language = language
	self.words = {}
	if not word:
	word = language
	if not definition:
	definition = language + ' is a word worthy of a language'
	self.words[word] = set([definition])
	print self.words

def get_language(self):
return self.language

def lookup_word(self, word, definition = None):
	print 'lookup_word', self.words
try:
	return self.words[word]
except:
	if definition:
	raise UknownWordException(word)
	else:
	raise UnknownDefinition(word, definition)

class CopyDictionary(Dictionary, pb.Copyable):

def getStateToCopy(self):
print 'state getting copied', self.language
return self.language, self.words

class DictionaryEditor(pb.Referenceable):

def remote_word_definition(self, lanague, word, definition):
pass

class RemoteDictionary(pb.RemoteCopy, Dictionary):

def setCopyableState(self, state):
print 'remote state receives copy', state
self.language = state[0]
self.words = state[1]

class Library(pb.Root):

dictionaries = []

def remote_define(self, language, word, definition):
	dictionary = self.remote_dictionary(language, word, definition)	
	try:
	definition_set = dictionary.lookup_word(word, definition)
	print 'got definition_set', definition_set
	if definition not in definition_set:
		print 'new definition'
		definition_set.add(definition)
	else:
		print 'existing definition'
	except Exception as e:
	print e
	print 'new word'
	dictionary.words[word] = set([definition])
	return dictionary.words
		

def remote_dictionary(self, language, word = None, definition = None):
for d in Library.dictionaries:
if d.get_language() == language:
print 'remote'
return d
print 'create copyable version'
dictionary = CopyDictionary(language, word, definition)
Library.dictionaries.append(dictionary)
return dictionary
from twisted.spread import pb
from example import CopyDictionary, RemoteDictionary
from twisted.internet import reactor
from twisted.internet import defer

factory = pb.PBClientFactory()
reactor.connectTCP("localhost", 7999, factory)

pb.setUnjellyableForClass(CopyDictionary, RemoteDictionary)

def use_dictionary(dictionary):
for w in dictionary.words.keys():
	for d in dictionary.words[w]:
	print w, d
reactor.callLater(10, use_dictionary, dictionary)

def goto_library():
return factory.getRootObject()

import sys
language = 'english'
if len(sys.argv) > 1:
language = sys.argv[1]

def test():
d = goto_library()
d.addCallback(lambda root: root.callRemote('dictionary', language))
d.addCallback(use_dictionary)
return d

reactor.callWhenRunning(test)
reactor.run()



library.sh
Description: Bourne shell script
from twisted.spread import pb
from twisted.internet import reactor
from twisted.internet import defer

factory = pb.PBClientFactory()
reactor.connectTCP("localhost", 7999, factory)

def goto_library():
return factory.getRootObject()

def define_result(ans, language, word, definition):
# audit submission later
print ans
reactor.stop()
import sys 
language = 'english'
if len(sys.argv) > 1:
language = sys.argv[1]
word = language
if len(sys.argv) > 2:
word = sys.argv[2]
definition = word + ' is part of ' + language
if len(sys.argv) > 3:
definition = sys.argv[3]

print 'language', language
print 'word', word
print 'definition', definition

def test():
d = goto_library()
d.addCallback(lambda root: root.callRemote('define', language, word, definition))
d.addCallback(define_result, language, word, definition)
return d

reactor.callWhenRunning(test)
reactor.run()

___
Twisted-Python mailing list
Twisted-Python@twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python


Re: [Twisted-Python] Embedding manhole interpreter into insults widget.

2014-08-07 Thread Maxim Lacrima
Hi,

Thanks for your explanation. Now I understand a lot better how things work.
I will try to implement "native" manhole widget. I think this will be a
good exercise for me to learn how terminals and `twisted.conch` work.

Thanks.


On 7 August 2014 14:53,  wrote:

> On 6 Aug, 06:14 pm, lacrima.ma...@gmail.com wrote:
>
>> Hello,
>>
>> I have been trying to create a widget that encloses manhole interpreter.
>> Here is somewhat hacky implementation that I came up with at this moment:
>>
>
> Widgets and the manhole interpreter are implemented using two pretty
> distinct approaches.
>
> As you've figured out, these approaches can be integrated (at least in one
> direction) using a terminal emulator - `twisted.conch.insults.helper.
> TerminalBuffer`.
>
> However, `TerminalBuffer` is an extremely low quality terminal emulator.
> Among its many flaws is that it uses a number of incredibly inefficient
> implementations for common terminal operations (many of its other flaws are
> along the lines of "it has a bug in the implementation of X").
>
> If I were going to create a manhole widget then I would do it "natively" -
> not by bridging the existing manhole protocol to the widget system with
> TerminalBuffer but by writing a new widget that does manhole stuff all by
> itself.
>
> I suggest that you might want to pursue this approach instead of trying to
> optimize and fix bugs in TerminalBuffer.
>
> Ultimately it would be nice if a widget-based manhole were *the* manhole
> and the current implementation went away.
>
> However, that said, as far as I know, no vt-style terminals support
> efficient redrawing for the "vertically scroll one portion of the terminal
> separated from another portion by a vertical divider".
>
> You will be able to avoid the redundant work of re-rendering the Python
> buffer representing the terminal state but you'll still have to re-
> transmit the bytes representing the entire terminal display to the terminal
> on each redraw - unless you avoid vertical dividers.
>
> Jean-Paul
>
>
> ___
> Twisted-Python mailing list
> Twisted-Python@twistedmatrix.com
> http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
>



-- 
Regards,
Maxim
___
Twisted-Python mailing list
Twisted-Python@twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python