Skip to content

Commit ec85d5a

Browse files
committed
multiple renderers now possible
1 parent 753d724 commit ec85d5a

File tree

9 files changed

+126
-123
lines changed

9 files changed

+126
-123
lines changed

development.ini

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ pyramid.includes =
1919
# debugtoolbar.hosts = 127.0.0.1 ::1
2020

2121
pyragit.repository_path = %(here)s
22-
pyragit.markdown_extension = .md
2322

2423
###
2524
# wsgi server configuration

pyragit/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def main(global_config, **settings):
1313
config = Configurator(settings=settings)
1414
config.include('pyramid_jinja2')
1515
config.include('pyragit.resources')
16-
config.include('pyragit.markdown')
16+
config.include('pyragit.markup')
1717
config.add_static_view('static', 'static', cache_max_age=3600)
1818
config.scan()
1919

pyragit/markdown.py

Lines changed: 0 additions & 28 deletions
This file was deleted.

pyragit/markup.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
''' setup of the markup renderers '''
2+
3+
import mistune
4+
import re
5+
6+
from mistune_contrib import highlight
7+
8+
9+
class HighlightRenderer(highlight.HighlightMixin, mistune.Renderer):
10+
''' Markdown renderer with syntax highlighting'''
11+
pass
12+
13+
14+
def render_text(content):
15+
''' a simple renderer for text documents: replace new lines with <br> '''
16+
return '<br>'.join(content.splitlines())
17+
18+
19+
def includeme(config):
20+
'''
21+
configures the rendering engines and attaches them to the request
22+
23+
Activate this setup using ``config.include('pyragit.markdown')``.
24+
'''
25+
md_renderer = HighlightRenderer(inlinestyles=False, linenos=False)
26+
render_markdown = mistune.Markdown(renderer=md_renderer)
27+
28+
renderer_dict = {
29+
'.md': render_markdown,
30+
'.txt': render_text
31+
}
32+
33+
def get_markup_renderer(filename):
34+
name, dot, ext = filename.rpartition('.')
35+
complete_extension = dot + ext
36+
return renderer_dict.get(complete_extension, None)
37+
38+
config.add_request_method(
39+
lambda request, filename: get_markup_renderer(filename),
40+
'get_markup_renderer'
41+
)

pyragit/resources.py

Lines changed: 75 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33

44
import pygit2
5+
import functools
56

67
from datetime import datetime
78
from pathlib import Path
@@ -11,41 +12,35 @@
1112
class BaseResource:
1213
''' base class for all resources '''
1314

14-
def __init__(self, name, parent, tree_entry, request):
15-
self.__name__ = name
15+
def __init__(self, tree_entry, parent):
16+
self.__name__ = tree_entry.name
1617
self.__parent__ = parent
1718
self.pygit2_tree_entry = tree_entry
18-
self.request = request
19-
self._pygit2_object = None
20-
self._last_commit = None
19+
self.request = parent.request
2120

2221
@property
22+
@functools.lru_cache(maxsize=128)
2323
def pygit2_object(self):
2424
''' lazy loading of the pygit2 object '''
25-
if self._pygit2_object is None:
26-
oid = self.pygit2_tree_entry.oid
27-
self._pygit2_object = self.request.repository[oid]
28-
return self._pygit2_object
25+
oid = self.pygit2_tree_entry.oid
26+
return self.request.repository[oid]
2927

3028
@property
3129
def type(self):
3230
''' returns the type of the resource, either 'tree' or 'blob' '''
33-
if self.__name__ is None:
34-
# Root has no name, but is a Folder
35-
return 'tree'
36-
return self.pygit2_tree_entry.type
31+
# Root has no tree entry, but is a Folder
32+
return 'tree' if self.__name__ is None else self.pygit2_tree_entry.type
3733

3834
@property
35+
@functools.lru_cache(maxsize=128)
3936
def last_commit(self):
4037
''' get the last commit of the resource
4138
4239
from https://stackoverflow.com/questions/13293052/pygit2-blob-history
43-
'''
44-
if self._last_commit:
45-
return self._last_commit
46-
40+
'''
4741
# loops through all the commits
4842
last_oid = None
43+
last_commit = None
4944
repo = self.request.repository
5045
for commit in repo.walk(repo.head.target, pygit2.GIT_SORT_TIME):
5146

@@ -56,14 +51,14 @@ def last_commit(self):
5651
oid = self.pygit2_tree_entry.oid
5752
has_changed = (oid != last_oid and last_oid)
5853
if has_changed:
59-
return self._last_commit
54+
return last_commit
6055
last_oid = oid
6156
else:
6257
last_oid = None
6358

64-
self._last_commit = commit
59+
last_commit = commit
6560

66-
return self._last_commit
61+
return last_commit
6762

6863
@property
6964
def author(self):
@@ -77,41 +72,39 @@ def date(self):
7772
class Folder(BaseResource):
7873
''' Resource representing a git tree (like a folder in a file system) '''
7974

75+
@property
76+
@functools.lru_cache(maxsize=128)
77+
def index(self):
78+
''' get the markup index file of the folder or None '''
79+
blobs = (e for e in self.pygit2_object if e.type=='blob')
80+
index_files = (e for e in blobs if e.name.lower().startswith('index.'))
81+
for entry in index_files:
82+
renderer = self.request.get_markup_renderer(entry.name)
83+
if renderer:
84+
return Markup(entry, self, renderer)
85+
return None
86+
8087
def __getitem__(self, key):
8188
''' Dict like access to child resources '''
8289

8390
# hidden files (starting with a dot) are forbidden to access
8491
if key.startswith('.'):
8592
raise KeyError
8693

87-
# try to directly access a tree entry,
88-
# only blob (binary file) and trees (folders) are allowed
89-
try:
90-
tree_entry = self.pygit2_object[key]
91-
if tree_entry.type == 'blob':
92-
return File(key, self, tree_entry, self.request)
93-
elif tree_entry.type == 'tree':
94-
return Folder(key, self, tree_entry, self.request)
95-
except KeyError:
96-
pass
94+
tree_entry = self.pygit2_object[key]
95+
if tree_entry.type == 'tree':
96+
return Folder(tree_entry, self)
97+
98+
if tree_entry.type != 'blob':
99+
# non file entry, might be a git note object
100+
# or something else
101+
raise KeyError
97102

98-
# look for a text-file, that should be rendered
99-
markdown = self._search_markdown_file(key)
100-
if markdown:
101-
return markdown
102-
103-
# nothing found, raise Error
104-
raise KeyError
105-
106-
def _search_markdown_file(self, name):
107-
''' look for a markdown file '''
108-
markdown_file = name + self.request.markdown_extension
109-
blobs = (e for e in self.pygit2_object if e.type=='blob')
110-
for entry in blobs:
111-
if entry.name.lower() == markdown_file.lower():
112-
return Markdown(name, self, entry, self.request)
113-
return None
114-
103+
renderer = self.request.get_markup_renderer(key)
104+
if renderer is None:
105+
return File(tree_entry, self)
106+
else:
107+
return Markup(tree_entry, self, renderer)
115108

116109
def __iter__(self):
117110
''' iterate over renderable child resources '''
@@ -121,30 +114,38 @@ def __iter__(self):
121114
# first list the folders
122115
trees = (e for e in ordered if e.type=='tree')
123116
for entry in trees:
124-
yield Folder(entry.name, self, entry, self.request)
125-
# then list the markdown files
126-
md_ext = self.request.markdown_extension
117+
yield Folder(entry, self)
118+
# then list the markup files
127119
blobs = (e for e in ordered if e.type=='blob')
128-
texts = (e for e in blobs if e.name.endswith(md_ext))
129-
for entry in texts:
130-
name = entry.name[:-len(md_ext)]
131-
if name != 'index':
132-
yield Markdown(name, self, entry, self.request)
133-
134-
@property
135-
def index(self):
136-
''' get the markdown index file of the folder or None '''
137-
return self._search_markdown_file('index')
120+
# except the index file used
121+
index_name = self.index.__name__ if self.index else None
122+
non_index = (e for e in blobs if e.name != index_name)
123+
for entry in non_index:
124+
renderer = self.request.get_markup_renderer(entry.name)
125+
if renderer:
126+
yield Markup(entry, self, renderer)
138127

139128

140129
class Root(Folder):
141130
''' the root resource for traversal '''
142131

143132
def __init__(self, request):
144-
super().__init__(None, None, None, request)
145-
head = request.repository.head
146-
self._last_commit = head.peel()
147-
self._pygit2_object = self._last_commit.tree
133+
self.__name__ = None
134+
self.__parent__ = None
135+
self.request = request
136+
137+
@property
138+
def pygit2_object(self):
139+
''' lazy loading of the pygit2 object not required on root resource'''
140+
return self.last_commit.tree
141+
142+
@property
143+
def last_commit(self):
144+
''' get the last commit of the resource
145+
146+
On the root resource, this is only a simple lookup
147+
'''
148+
return self.request.repository.head.peel()
148149

149150

150151
class File(BaseResource):
@@ -161,13 +162,21 @@ def size(self):
161162
return self.pygit2_object.size
162163

163164

164-
class Markdown(BaseResource):
165-
''' Resource for a Markdown file that could be rendered '''
165+
class Markup(BaseResource):
166+
''' Resource for a markup file that could be rendered '''
167+
168+
def __init__(self, tree_entry, parent, rendering_func):
169+
super().__init__(tree_entry, parent)
170+
self.renderer = rendering_func
166171

167172
@property
168173
def text(self):
169174
''' access the text content of the file '''
170175
return self.pygit2_object.data.decode('utf-8')
176+
177+
def render(self):
178+
''' returned the rendered representation of the markup file'''
179+
return self.renderer(self.text)
171180

172181

173182

@@ -191,16 +200,5 @@ def includeme(config):
191200
reify=True
192201
)
193202

194-
markdown_extension = settings.get('pyragit.markdown_extension', None)
195-
if markdown_extension is None:
196-
raise ConfigurationError('Markdown Extension not set')
197-
198-
# make request.markdown_extension available for use in Pyramid
199-
config.add_request_method(
200-
lambda r: markdown_extension,
201-
'markdown_extension',
202-
reify=True
203-
)
204-
205203
# set the root factory for traverssal
206204
config.set_root_factory(Root)

pyragit/templates/folder.jinja2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
{% block text %}
44
{% if context.index %}
5-
{{ request.render_markdown(context.index.text)|safe }}
5+
{{ context.index.render()|safe }}
66
{% else %}
77
<h1> Crivens ! </h1>
88
<p>

pyragit/templates/layout.jinja2

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,10 @@
1010
{% endif %}
1111
{% for resource in folder %}
1212
<li class="nav-item">
13-
{% if resource.__name__ == context.__name__ %}
14-
<a class="nav-link active" href="{{request.resource_path(resource)}}">
15-
<span class="pyragit-resource-type">&gt;</span>
16-
{{resource.__name__}}
17-
</a>
18-
{% else %}
19-
<a class="nav-link" href="{{request.resource_path(resource)}}">
20-
<span class="pyragit-resource-type">{{'d' if resource.type == 'tree' else 'f'}}</span>
21-
{{resource.__name__}}{{'/' if resource.type == 'tree'}}
22-
</a>
23-
{% endif %}
13+
<a class="nav-link" href="{{request.resource_path(resource)}}">
14+
<span class="pyragit-resource-type">{% if resource.__name__ == context.__name__ %}&gt;{% elif resource.type == 'tree'%}d{% else %}f{% endif %}</span>
15+
{{resource.__name__}}{{'/' if resource.type == 'tree'}}
16+
</a>
2417
</li>
2518
{% endfor %}
2619
</ul>

pyragit/templates/markdown.jinja2 renamed to pyragit/templates/markup.jinja2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{% extends "layout.jinja2" %}
22

33
{% block text %}
4-
{{ request.render_markdown(context.text)|safe }}
4+
{{ context.render()|safe }}
55
{% endblock text %}
66

77
{% block explore %}

pyragit/views.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ def folder(context, request):
1717

1818

1919
@view_config(
20-
context='pyragit.resources.Markdown',
21-
renderer='templates/markdown.jinja2'
20+
context='pyragit.resources.Markup',
21+
renderer='templates/markup.jinja2'
2222
)
2323
def markdown(context, request):
24-
''' renders a Markdown context '''
24+
''' renders a markup context '''
2525
return { }
2626

2727

0 commit comments

Comments
 (0)