Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Stricter document representation, and crazy meta-magical Python reader
- Loading branch information
Showing
6 changed files
with
217 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
*~ | ||
*.pyc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
""" | ||
Stuff for format implementations to subclass / use. | ||
""" | ||
|
||
|
||
class PythReader(object): | ||
""" | ||
Base class for all Pyth readers. | ||
Readers must implement these methods. | ||
""" | ||
|
||
@classmethod | ||
def read(self, source): | ||
""" | ||
source: An object to read the document from. | ||
Usually (but not necessarily) a file object. | ||
Returns: A pyth.document.Document object. | ||
""" | ||
pass | ||
|
||
|
||
|
||
class PythWriter(object): | ||
""" | ||
Base class for all Pyth writers. | ||
Writers must implement these methods. | ||
""" | ||
|
||
@classmethod | ||
def write(self, document, target=None): | ||
""" | ||
document: An instance of pyth.document.Document | ||
target: An object to write the document to. | ||
Usually (but not necessarily) a file object. | ||
If target is None, return something sensible | ||
(like a StringIO object) | ||
Returns: The target object | ||
""" | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
""" | ||
Document format plugins | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
""" | ||
Python object input | ||
""" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
""" | ||
Write Pyth documents straight in Python, a la Nevow's Stan. | ||
""" | ||
|
||
from pyth.format import PythReader | ||
from pyth.document import * | ||
|
||
|
||
class PythonReader(PythReader): | ||
|
||
@classmethod | ||
def read(self, source): | ||
""" | ||
source: A list of P objects. | ||
""" | ||
return Document(content=[c.toPyth() for c in source]) | ||
|
||
|
||
|
||
class _Shortcut(object): | ||
def __init__(self, key): | ||
self.key = key | ||
|
||
def asDict(self): | ||
return dict(((self.key, True),)) | ||
|
||
|
||
BOLD = _Shortcut("bold") | ||
ITALIC = _Shortcut("italic") | ||
UNDERLINE = _Shortcut("underline") | ||
|
||
|
||
def _MetaPythonBase(): | ||
""" | ||
Return a metaclass which implements __getitem__, | ||
allowing e.g. P[...] instead of P()[...] | ||
""" | ||
|
||
class MagicGetItem(type): | ||
def __new__(mcs, name, bases, dict): | ||
klass = type.__new__(mcs, name, bases, dict) | ||
mcs.__getitem__ = lambda _, k: klass()[k] | ||
return klass | ||
|
||
return MagicGetItem | ||
|
||
|
||
|
||
class _PythonBase(object): | ||
""" | ||
Base class for Python markup objects, providing | ||
stan-ish interface | ||
""" | ||
|
||
def __init__(self, *shortcuts, **properties): | ||
self.properties = properties.copy() | ||
|
||
for shortcut in shortcuts: | ||
self.properties.update(shortcut.asDict()) | ||
|
||
self.content = [] | ||
|
||
|
||
def toPyth(self): | ||
return self.pythType(self.properties, | ||
[c.toPyth() for c in self.content]) | ||
|
||
|
||
def __getitem__(self, item): | ||
|
||
if isinstance(item, tuple): | ||
for i in item: self [i] | ||
elif isinstance(item, int): | ||
return self.content[item] | ||
else: | ||
self.content.append(item) | ||
|
||
return self | ||
|
||
|
||
def __str__(self): | ||
return "%s(%s) [ %s ]" % ( | ||
self.__class__.__name__, | ||
", ".join("%s=%s" % (k, repr(v)) for (k,v) in self.properties.iteritems()), | ||
", ".join(repr(x) for x in self.content)) | ||
|
||
|
||
|
||
class P(_PythonBase): | ||
__metaclass__ = _MetaPythonBase() | ||
pythType = Paragraph | ||
|
||
|
||
class L(_PythonBase): | ||
__metaclass__ = _MetaPythonBase() | ||
pythType = List | ||
|
||
|
||
class T(_PythonBase): | ||
__metaclass__ = _MetaPythonBase() | ||
__repr__ = _PythonBase.__str__ | ||
|
||
def toPyth(self): | ||
return Text(self.properties, self.content) | ||
|
||
|
||
|
||
if __name__ == "__main__": | ||
p = P [ | ||
T(BOLD), | ||
T(ITALIC, url=u'http://www.google.com') [ u"Hello World" ], | ||
T [ u"Hee hee hee" ] [ u"This seems to work" ] | ||
] | ||
|
||
doc = PythonReader.read((p,)) | ||
|