1
1
# -*- coding: utf-8 -*-
2
2
from abc import ABCMeta
3
3
4
+ from pathlib import Path
5
+
4
6
from fastapi import Response
5
7
from fastapi .responses import JSONResponse
6
8
from fastapi .templating import Jinja2Templates
12
14
from pyldapi .exceptions import ProfilesMediatypesException
13
15
import re
14
16
import connegp
17
+ from .data import MEDIATYPE_NAMES , RDF_MEDIATYPES
15
18
16
- templates = Jinja2Templates ( directory = " templates")
17
- MEDIATYPE_NAMES = None
19
+ templates_dir = Path ( __file__ ). parent . parent / "pyldapi" / " templates"
20
+ templates = Jinja2Templates ( directory = str ( templates_dir ))
18
21
19
22
20
23
class Renderer (object , metaclass = ABCMeta ):
21
24
"""
22
25
Abstract class as a parent for classes that validate the profiles & mediatypes for an API-delivered resource (typically
23
26
either registers or objects) and also creates an 'alternates profile' for them, based on all available profiles & mediatypes.
24
27
"""
25
- global MEDIATYPE_NAMES
26
-
27
- RDF_MEDIA_TYPES = ['text/turtle' , 'application/rdf+xml' , 'application/ld+json' , 'text/n3' , 'application/n-triples' ]
28
- RDF_SERIALIZER_TYPES_MAP = {
29
- "text/turtle" : "turtle" ,
30
- "text/n3" : "n3" ,
31
- "application/n-triples" : "nt" ,
32
- "application/ld+json" : "json-ld" ,
33
- "application/rdf+xml" : "xml" ,
34
- # Some common but incorrect mimetypes
35
- "application/rdf" : "xml" ,
36
- "application/rdf xml" : "xml" ,
37
- "application/json" : "json-ld" ,
38
- "application/ld json" : "json-ld" ,
39
- "text/ttl" : "turtle" ,
40
- "text/ntriples" : "nt" ,
41
- "text/n-triples" : "nt" ,
42
- "text/plain" : "nt" , # text/plain is the old/deprecated mimetype for n-triples
43
- }
44
28
45
29
def __init__ (self ,
46
30
request ,
47
31
instance_uri ,
48
32
profiles ,
49
33
default_profile_token ,
50
- alternates_template = None ,
51
- ** kwargs
52
34
):
53
35
"""
54
36
Constructor
@@ -73,9 +55,6 @@ def __init__(self,
73
55
self .request = request
74
56
self .instance_uri = instance_uri
75
57
76
- # self.mediatype_names = kwargs.get('MEDIATYPE_NAMES')
77
- self .local_uris = kwargs .get ('LOCAL_URIS' )
78
-
79
58
# ensure alternates token isn't hogged by user
80
59
for k , v in profiles .items ():
81
60
if k == 'alternates' :
@@ -87,7 +66,7 @@ def __init__(self,
87
66
'http://www.w3.org/ns/dx/conneg/altr' , # the ConnegP URI for Alt Rep Data Model
88
67
'Alternate Representations' ,
89
68
'The representation of the resource that lists all other representations (profiles and Media Types)' ,
90
- ['text/html' , 'application/json' ] + self . RDF_MEDIA_TYPES ,
69
+ ['text/html' , 'application/json' ] + RDF_MEDIATYPES ,
91
70
'text/html' ,
92
71
languages = ['en' ], # default 'en' only for now
93
72
)
@@ -105,9 +84,6 @@ def __init__(self,
105
84
106
85
self .default_profile_token = default_profile_token
107
86
108
- # TODO: supply an alternates.html template
109
- self .alt_template = alternates_template
110
-
111
87
# get profile & mediatype for this request, flag any errors but do not except out
112
88
self .profile = self ._get_profile ()
113
89
self .mediatype = self ._get_mediatype ()
@@ -451,20 +427,7 @@ def _make_rdf_response(self, graph, mimetype=None, headers=None, delete_graph=Tr
451
427
if headers is None :
452
428
headers = self .headers
453
429
454
- if mimetype is not None :
455
- response_mimetype = mimetype
456
- serial_mediatype = self .RDF_SERIALIZER_TYPES_MAP .get (mimetype )
457
- elif self .mediatype is not None :
458
- response_mimetype = self .mediatype
459
- if self .mediatype in ['application/rdf+json' , 'application/json' ]:
460
- serial_mediatype = 'json-ld'
461
- else :
462
- serial_mediatype = self .RDF_SERIALIZER_TYPES_MAP .get (self .mediatype )
463
- else :
464
- serial_mediatype = "turtle"
465
- response_mimetype = "text/turtle"
466
-
467
- response_text = graph .serialize (format = serial_mediatype , encoding = 'utf-8' )
430
+ response_text = graph .serialize (format = mimetype or "text/turtle" )
468
431
469
432
if delete_graph :
470
433
# destroy the triples in the triplestore, then delete the triplestore
@@ -475,11 +438,34 @@ def _make_rdf_response(self, graph, mimetype=None, headers=None, delete_graph=Tr
475
438
476
439
return Response (
477
440
response_text ,
478
- media_type = response_mimetype ,
441
+ media_type = mimetype ,
479
442
headers = headers
480
443
)
481
444
482
- def _render_alt_profile_html (self , template_context = None ):
445
+ def _render_alt_profile_html (
446
+ self ,
447
+ alt_template : str = "alt.html" ,
448
+ additional_alt_template_context = None ,
449
+ alt_template_context_replace = False
450
+ ):
451
+ """Renders the Alternates Profile in HTML
452
+
453
+ If an alt_template value (str, file name) is given, a template of that name will be looked for in the app's
454
+ template directory, else alt.html will be used.
455
+
456
+ If a dictionary is given for additional_alt_template_context, this will either replace the standard template
457
+ context, if alt_template_context_replace is True, or just be added to it, if alt_template_context_replace is
458
+ False
459
+
460
+ :param alt_template: the name of the template to use
461
+ :type alt_template: str (file name, within the application's templates directory)
462
+ :param additional_alt_template_context: Additional or complete context for the template
463
+ :type additional_alt_template_context: dict
464
+ :param alt_template_context_replace: To replace (True) or add to (False) the standard template context
465
+ :type alt_template_context_replace: bool
466
+ :return: a rendered template (HTML)
467
+ :rtype: TemplateResponse
468
+ """
483
469
profiles = {}
484
470
for token , profile in self .profiles .items ():
485
471
profiles [token ] = {
@@ -495,13 +481,16 @@ def _render_alt_profile_html(self, template_context=None):
495
481
'uri' : self .instance_uri ,
496
482
'default_profile_token' : self .default_profile_token ,
497
483
'profiles' : profiles ,
498
- 'MEDIATYPE_NAMES ' : MEDIATYPE_NAMES ,
484
+ 'mediatype_names ' : MEDIATYPE_NAMES ,
499
485
'request' : self .request
500
486
}
501
- if template_context is not None and isinstance (template_context , dict ):
502
- _template_context .update (template_context )
487
+ if additional_alt_template_context is not None and isinstance (additional_alt_template_context , dict ):
488
+ if alt_template_context_replace :
489
+ _template_context = additional_alt_template_context
490
+ else :
491
+ _template_context .update (additional_alt_template_context )
503
492
504
- return templates .TemplateResponse (self . alt_template or 'alt.html' ,
493
+ return templates .TemplateResponse (alt_template ,
505
494
context = _template_context ,
506
495
headers = self .headers )
507
496
@@ -531,7 +520,7 @@ def _render_alt_profile(self):
531
520
return self
532
521
if self .mediatype == 'text/html' :
533
522
return self ._render_alt_profile_html ()
534
- elif self .mediatype in Renderer . RDF_MEDIA_TYPES :
523
+ elif self .mediatype in RDF_MEDIATYPES :
535
524
return self ._render_alt_profile_rdf ()
536
525
else : # application/json
537
526
return self ._render_alt_profile_json ()
0 commit comments