comparison roundup/cgi/templating.py @ 7036:7847c9bdb631

flake8 fixes: lambda assign squash, over/under indent, var names Fix: Squashed with a noqa: E731 do not assign a lambda expression, use a def fixed some of the rest. E741 ambiguous variable name 'l' E128 continuation line under-indented for visual indent E701 multiple statements on one line (colon) E127 continuation line over-indented for visual indent E111 indentation is not a multiple of 4 first tranch of changes about 1/3 of the number of warnings.
author John Rouillard <rouilj@ieee.org>
date Mon, 10 Oct 2022 15:07:17 -0400
parents edaf7086cb2e
children 22183e7d1443
comparison
equal deleted inserted replaced
7035:edaf7086cb2e 7036:7847c9bdb631
71 extras = {'fenced-code-blocks': {}, 'nofollow': None} 71 extras = {'fenced-code-blocks': {}, 'nofollow': None}
72 if config['MARKDOWN_BREAK_ON_NEWLINE']: 72 if config['MARKDOWN_BREAK_ON_NEWLINE']:
73 extras['break-on-newline'] = True 73 extras['break-on-newline'] = True
74 return extras 74 return extras
75 75
76 markdown = lambda s, c: Markdown(safe_mode='escape', extras=_extras(c)).convert(s) 76 markdown = lambda s, c: Markdown(safe_mode='escape', extras=_extras(c)).convert(s) # noqa: E731
77 except ImportError: 77 except ImportError:
78 markdown = None 78 markdown = None
79 79
80 return markdown 80 return markdown
81 81
134 extensions = [SafeHtml(), 'fenced_code'] 134 extensions = [SafeHtml(), 'fenced_code']
135 if config['MARKDOWN_BREAK_ON_NEWLINE']: 135 if config['MARKDOWN_BREAK_ON_NEWLINE']:
136 extensions.append('nl2br') 136 extensions.append('nl2br')
137 return extensions 137 return extensions
138 138
139 markdown = lambda s, c: markdown_impl(s, extensions=_extensions(c)) 139 markdown = lambda s, c: markdown_impl(s, extensions=_extensions(c)) # noqa: E731
140 except ImportError: 140 except ImportError:
141 markdown = None 141 markdown = None
142 142
143 return markdown 143 return markdown
144 144
187 options = {'renderer': LinkRendererWithRel(escape=True)} 187 options = {'renderer': LinkRendererWithRel(escape=True)}
188 if config['MARKDOWN_BREAK_ON_NEWLINE']: 188 if config['MARKDOWN_BREAK_ON_NEWLINE']:
189 options['hard_wrap'] = True 189 options['hard_wrap'] = True
190 return options 190 return options
191 191
192 markdown = lambda s, c: mistune.markdown(s, **_options(c)) 192 markdown = lambda s, c: mistune.markdown(s, **_options(c)) # noqa: E731
193 except ImportError: 193 except ImportError:
194 markdown = None 194 markdown = None
195 195
196 return markdown 196 return markdown
197 197
236 else: 236 else:
237 self._ = TranslationService.get_translation().gettext 237 self._ = TranslationService.get_translation().gettext
238 238
239 def __str__(self): 239 def __str__(self):
240 return self._('You are not allowed to %(action)s ' 240 return self._('You are not allowed to %(action)s '
241 'items of class %(class)s') % { 241 'items of class %(class)s') % {
242 'action': self.action, 'class': self.klass} 242 'action': self.action, 'class': self.klass}
243 243
244 244
245 # --- Template Loader API 245 # --- Template Loader API
246 246
247 class LoaderBase: 247 class LoaderBase:
326 326
327 def add_loader(self, loader): 327 def add_loader(self, loader):
328 self.loaders.append(loader) 328 self.loaders.append(loader)
329 329
330 def check(self, name): 330 def check(self, name):
331 for l in self.loaders: 331 for loader in self.loaders:
332 if l.check(name): 332 if loader.check(name):
333 return True 333 return True
334 334
335 def load(self, name): 335 def load(self, name):
336 for l in self.loaders: 336 for loader in self.loaders:
337 if l.check(name): 337 if loader.check(name):
338 return l.load(name) 338 return loader.load(name)
339 339
340 def __getitem__(self, name): 340 def __getitem__(self, name):
341 """Needed for TAL templates compatibility""" 341 """Needed for TAL templates compatibility"""
342 # [ ] document root and helper templates 342 # [ ] document root and helper templates
343 try: 343 try:
458 'i18n': client.translator 458 'i18n': client.translator
459 } 459 }
460 # add in the item if there is one 460 # add in the item if there is one
461 if client.nodeid: 461 if client.nodeid:
462 c['context'] = HTMLItem(client, classname, client.nodeid, 462 c['context'] = HTMLItem(client, classname, client.nodeid,
463 anonymous=1) 463 anonymous=1)
464 elif classname in client.db.classes: 464 elif classname in client.db.classes:
465 c['context'] = HTMLClass(client, classname, anonymous=1) 465 c['context'] = HTMLClass(client, classname, anonymous=1)
466 return c 466 return c
467 467
468 468
493 return self[attr] 493 return self[attr]
494 except KeyError: 494 except KeyError:
495 raise AttributeError(attr) 495 raise AttributeError(attr)
496 496
497 def classes(self): 497 def classes(self):
498 l = sorted(self._client.db.classes.keys()) 498 class_keys = sorted(self._client.db.classes.keys())
499 m = [] 499 m = []
500 for item in l: 500 for item in class_keys:
501 m.append(HTMLClass(self._client, item)) 501 m.append(HTMLClass(self._client, item))
502 return m 502 return m
503 503
504 504
505 num_re = re.compile(r'^-?\d+$') 505 num_re = re.compile(r'^-?\d+$')
544 label = linkcl.get(entry, key) 544 label = linkcl.get(entry, key)
545 except IndexError: 545 except IndexError:
546 # fall back to id if illegal (avoid template crash) 546 # fall back to id if illegal (avoid template crash)
547 label = entry 547 label = entry
548 # fall back to designator if label is None 548 # fall back to designator if label is None
549 if label is None: label = '%s%s' % (linkcl.classname, entry) 549 if label is None:
550 label = '%s%s' % (linkcl.classname, entry)
550 l.append(label) 551 l.append(label)
551 else: 552 else:
552 l.append(entry) 553 l.append(entry)
553 return l 554 return l
554 555
575 The latter is xhtml. Recognize booleans by: 576 The latter is xhtml. Recognize booleans by:
576 value is None 577 value is None
577 Code can use None to indicate a pure boolean. 578 Code can use None to indicate a pure boolean.
578 ''' 579 '''
579 return ' '.join(['%s="%s"' % (k, html_escape(str(v), True)) 580 return ' '.join(['%s="%s"' % (k, html_escape(str(v), True))
580 if v is not None else '%s' % (k) 581 if v is not None else '%s' % (k)
581 for k, v in sorted(attrs.items())]) 582 for k, v in sorted(attrs.items())])
582 583
583 584
584 def xhtml_cgi_escape_attrs(**attrs): 585 def xhtml_cgi_escape_attrs(**attrs):
585 ''' Boolean attributes like 'disabled', 'required' 586 ''' Boolean attributes like 'disabled', 'required'
586 are represented with a value that is the same as 587 are represented with a value that is the same as
589 The latter is html4 or 5. Recognize booleans by: 590 The latter is html4 or 5. Recognize booleans by:
590 value is None 591 value is None
591 Code can use None to indicate a pure boolean. 592 Code can use None to indicate a pure boolean.
592 ''' 593 '''
593 return ' '.join(['%s="%s"' % (k, html_escape(str(v), True)) 594 return ' '.join(['%s="%s"' % (k, html_escape(str(v), True))
594 if v is not None else '%s="%s"' % (k, k) 595 if v is not None else '%s="%s"' % (k, k)
595 for k, v in sorted(attrs.items())]) 596 for k, v in sorted(attrs.items())])
596 597
597 598
598 def input_html4(**attrs): 599 def input_html4(**attrs):
599 """Generate an 'input' (html4) element with given attributes""" 600 """Generate an 'input' (html4) element with given attributes"""
600 _set_input_default_args(attrs) 601 _set_input_default_args(attrs)
625 626
626 def gettext(self, msgid): 627 def gettext(self, msgid):
627 """Return the localized translation of msgid""" 628 """Return the localized translation of msgid"""
628 if self._context is None: 629 if self._context is None:
629 self._context = context(self._client) 630 self._context = context(self._client)
630 return self._client.translator.translate(domain="roundup", 631 return self._client.translator.translate(
631 msgid=msgid, context=self._context) 632 domain="roundup", msgid=msgid, context=self._context)
632 633
633 _ = gettext 634 _ = gettext
634 635
635 636
636 class HTMLPermissions(object): 637 class HTMLPermissions(object):
639 """ Raise the Unauthorised exception if the user's not permitted to 640 """ Raise the Unauthorised exception if the user's not permitted to
640 view this class. 641 view this class.
641 """ 642 """
642 if not self.is_view_ok(): 643 if not self.is_view_ok():
643 raise Unauthorised("view", self._classname, 644 raise Unauthorised("view", self._classname,
644 translator=self._client.translator) 645 translator=self._client.translator)
645 646
646 def edit_check(self): 647 def edit_check(self):
647 """ Raise the Unauthorised exception if the user's not permitted to 648 """ Raise the Unauthorised exception if the user's not permitted to
648 edit items of this class. 649 edit items of this class.
649 """ 650 """
650 if not self.is_edit_ok(): 651 if not self.is_edit_ok():
651 raise Unauthorised("edit", self._classname, 652 raise Unauthorised("edit", self._classname,
652 translator=self._client.translator) 653 translator=self._client.translator)
653 654
654 def retire_check(self): 655 def retire_check(self):
655 """ Raise the Unauthorised exception if the user's not permitted to 656 """ Raise the Unauthorised exception if the user's not permitted to
656 retire items of this class. 657 retire items of this class.
657 """ 658 """
658 if not self.is_retire_ok(): 659 if not self.is_retire_ok():
659 raise Unauthorised("retire", self._classname, 660 raise Unauthorised("retire", self._classname,
660 translator=self._client.translator) 661 translator=self._client.translator)
661 662
662 663
663 class HTMLClass(HTMLInputMixin, HTMLPermissions): 664 class HTMLClass(HTMLInputMixin, HTMLPermissions):
664 """ Accesses through a class (either through *class* or *db.<classname>*) 665 """ Accesses through a class (either through *class* or *db.<classname>*)
665 """ 666 """
679 680
680 def is_edit_ok(self): 681 def is_edit_ok(self):
681 """ Is the user allowed to Create the current class? 682 """ Is the user allowed to Create the current class?
682 """ 683 """
683 perm = self._db.security.hasPermission 684 perm = self._db.security.hasPermission
684 return perm('Web Access', self._client.userid) and perm('Create', 685 return perm('Web Access', self._client.userid) and perm(
685 self._client.userid, self._classname) 686 'Create', self._client.userid, self._classname)
686 687
687 def is_retire_ok(self): 688 def is_retire_ok(self):
688 """ Is the user allowed to retire items of the current class? 689 """ Is the user allowed to retire items of the current class?
689 """ 690 """
690 perm = self._db.security.hasPermission 691 perm = self._db.security.hasPermission
691 return perm('Web Access', self._client.userid) and perm('Retire', 692 return perm('Web Access', self._client.userid) and perm(
692 self._client.userid, self._classname) 693 'Retire', self._client.userid, self._classname)
693 694
694 def is_restore_ok(self): 695 def is_restore_ok(self):
695 """ Is the user allowed to restore retired items of the current class? 696 """ Is the user allowed to restore retired items of the current class?
696 """ 697 """
697 perm = self._db.security.hasPermission 698 perm = self._db.security.hasPermission
698 return perm('Web Access', self._client.userid) and perm('Restore', 699 return perm('Web Access', self._client.userid) and perm(
699 self._client.userid, self._classname) 700 'Restore', self._client.userid, self._classname)
700 701
701 def is_view_ok(self): 702 def is_view_ok(self):
702 """ Is the user allowed to View the current class? 703 """ Is the user allowed to View the current class?
703 """ 704 """
704 perm = self._db.security.hasPermission 705 perm = self._db.security.hasPermission
705 return perm('Web Access', self._client.userid) and perm('View', 706 return perm('Web Access', self._client.userid) and perm(
706 self._client.userid, self._classname) 707 'View', self._client.userid, self._classname)
707 708
708 def is_only_view_ok(self): 709 def is_only_view_ok(self):
709 """ Is the user only allowed to View (ie. not Create) the current class? 710 """ Is the user only allowed to View (ie. not Create) the current class?
710 """ 711 """
711 return self.is_view_ok() and not self.is_edit_ok() 712 return self.is_view_ok() and not self.is_edit_ok()
731 # look up the correct HTMLProperty class 732 # look up the correct HTMLProperty class
732 for klass, htmlklass in propclasses: 733 for klass, htmlklass in propclasses:
733 if not isinstance(prop, klass): 734 if not isinstance(prop, klass):
734 continue 735 continue
735 return htmlklass(self._client, self._classname, None, prop, item, 736 return htmlklass(self._client, self._classname, None, prop, item,
736 None, self._anonymous) 737 None, self._anonymous)
737 738
738 # no good 739 # no good
739 raise KeyError(item) 740 raise KeyError(item)
740 741
741 def __getattr__(self, attr): 742 def __getattr__(self, attr):
783 784
784 def list(self, sort_on=None): 785 def list(self, sort_on=None):
785 """ List all items in this class. 786 """ List all items in this class.
786 """ 787 """
787 # get the list and sort it nicely 788 # get the list and sort it nicely
788 l = self._klass.list() 789 class_list = self._klass.list()
789 keyfunc = make_key_function(self._db, self._classname, sort_on) 790 keyfunc = make_key_function(self._db, self._classname, sort_on)
790 l.sort(key=keyfunc) 791 class_list.sort(key=keyfunc)
791 792
792 # check perms 793 # check perms
793 check = self._client.db.security.hasPermission 794 check = self._client.db.security.hasPermission
794 userid = self._client.userid 795 userid = self._client.userid
795 if not check('Web Access', userid): 796 if not check('Web Access', userid):
796 return [] 797 return []
797 798
798 l = [HTMLItem(self._client, self._classname, id) for id in l 799 class_list = [HTMLItem(self._client, self._classname, id)
799 if check('View', userid, self._classname, itemid=id)] 800 for id in class_list if
800 801 check('View', userid, self._classname, itemid=id)]
801 return l 802
803 return class_list
802 804
803 def csv(self): 805 def csv(self):
804 """ Return the items of this class as a chunk of CSV text. 806 """ Return the items of this class as a chunk of CSV text.
805 """ 807 """
806 props = self.propnames() 808 props = self.propnames()
814 for nodeid in self._klass.list(): 816 for nodeid in self._klass.list():
815 l = [] 817 l = []
816 for name in props: 818 for name in props:
817 # check permission to view this property on this item 819 # check permission to view this property on this item
818 if not check('View', userid, itemid=nodeid, 820 if not check('View', userid, itemid=nodeid,
819 classname=self._klass.classname, property=name): 821 classname=self._klass.classname, property=name):
820 raise Unauthorised('view', self._klass.classname, 822 raise Unauthorised('view', self._klass.classname,
821 translator=self._client.translator) 823 translator=self._client.translator)
822 value = self._klass.get(nodeid, name) 824 value = self._klass.get(nodeid, name)
823 if value is None: 825 if value is None:
824 l.append('') 826 l.append('')
825 elif isinstance(value, type([])): 827 elif isinstance(value, type([])):
826 l.append(':'.join(map(str, value))) 828 l.append(':'.join(map(str, value)))
857 859
858 check = security.hasPermission 860 check = security.hasPermission
859 if not check('Web Access', userid): 861 if not check('Web Access', userid):
860 return [] 862 return []
861 863
862 l = [HTMLItem(self._client, self.classname, id) 864 filtered = [HTMLItem(self._client, self.classname, id)
863 for id in self._klass.filter(None, filterspec, sort, group) 865 for id in self._klass.filter(None, filterspec, sort, group)
864 if check('View', userid, self.classname, itemid=id)] 866 if check('View', userid, self.classname, itemid=id)]
865 return l 867 return filtered
866 868
867 def classhelp(self, properties=None, label=''"(list)", width='500', 869 def classhelp(self, properties=None, label=''"(list)", width='500',
868 height='600', property='', form='itemSynopsis', 870 height='600', property='', form='itemSynopsis',
869 pagesize=50, inputtype="checkbox", html_kwargs={}, 871 pagesize=50, inputtype="checkbox", html_kwargs={},
870 group='', sort=None, filter=None): 872 group='', sort=None, filter=None):
871 """Pop up a javascript window with class help 873 """Pop up a javascript window with class help
872 874
873 This generates a link to a popup window which displays the 875 This generates a link to a popup window which displays the
874 properties indicated by "properties" of the class named by 876 properties indicated by "properties" of the class named by
875 "classname". The "properties" should be a comma-separated list 877 "classname". The "properties" should be a comma-separated list
923 (name, values) = x.split('=') 925 (name, values) = x.split('=')
924 names.append(name) 926 names.append(name)
925 filtervalues.append('&amp;%s=%s' % (name, urllib_.quote(values))) 927 filtervalues.append('&amp;%s=%s' % (name, urllib_.quote(values)))
926 filter = '&amp;@filter=%s%s' % (','.join(names), ''.join(filtervalues)) 928 filter = '&amp;@filter=%s%s' % (','.join(names), ''.join(filtervalues))
927 else: 929 else:
928 filter = '' 930 filter = ''
929 help_url = "%s?@startwith=0&amp;@template=help&amp;"\ 931 help_url = "%s?@startwith=0&amp;@template=help&amp;"\
930 "properties=%s%s%s%s%s%s&amp;@pagesize=%s%s" % \ 932 "properties=%s%s%s%s%s%s&amp;@pagesize=%s%s" % \
931 (self.classname, properties, property, form, type, 933 (self.classname, properties, property, form, type,
932 group, sort, pagesize, filter) 934 group, sort, pagesize, filter)
933 onclick = "javascript:help_window('%s', '%s', '%s');return false;" % \ 935 onclick = "javascript:help_window('%s', '%s', '%s');return false;" % \
934 (help_url, width, height) 936 (help_url, width, height)
935 return ('<a class="classhelp" data-helpurl="%s" ' 937 return ('<a class="classhelp" data-helpurl="%s" '
936 'data-width="%s" data-height="%s" href="%s" ' 938 'data-width="%s" data-height="%s" href="%s" '
937 'onclick="%s" %s>%s</a>') % ( 939 'onclick="%s" %s>%s</a>') % (
950 if not self.is_edit_ok(): 952 if not self.is_edit_ok():
951 return '' 953 return ''
952 954
953 return \ 955 return \
954 self.input(type="submit", name="submit_button", 956 self.input(type="submit", name="submit_button",
955 value=self._(label), **html_kwargs) + \ 957 value=self._(label), **html_kwargs) + \
956 '\n' + \ 958 '\n' + \
957 self.input(type="hidden", name="@csrf", 959 self.input(type="hidden", name="@csrf",
958 value=anti_csrf_nonce(self._client)) + \ 960 value=anti_csrf_nonce(self._client)) + \
959 '\n' + \ 961 '\n' + \
960 self.input(type="hidden", name="@action", value=action) 962 self.input(type="hidden", name="@action", value=action)
961 963
962 def history(self, **args): 964 def history(self, **args):
963 if not self.is_view_ok(): 965 if not self.is_view_ok():
1003 1005
1004 def is_edit_ok(self): 1006 def is_edit_ok(self):
1005 """ Is the user allowed to Edit this item? 1007 """ Is the user allowed to Edit this item?
1006 """ 1008 """
1007 perm = self._db.security.hasPermission 1009 perm = self._db.security.hasPermission
1008 return perm('Web Access', self._client.userid) and perm('Edit', 1010 return perm('Web Access', self._client.userid) and perm(
1009 self._client.userid, self._classname, itemid=self._nodeid) 1011 'Edit', self._client.userid, self._classname, itemid=self._nodeid)
1010 1012
1011 def is_retire_ok(self): 1013 def is_retire_ok(self):
1012 """ Is the user allowed to Reture this item? 1014 """ Is the user allowed to Reture this item?
1013 """ 1015 """
1014 perm = self._db.security.hasPermission 1016 perm = self._db.security.hasPermission
1015 return perm('Web Access', self._client.userid) and perm('Retire', 1017 return perm('Web Access', self._client.userid) and perm(
1016 self._client.userid, self._classname, itemid=self._nodeid) 1018 'Retire', self._client.userid, self._classname,
1019 itemid=self._nodeid)
1017 1020
1018 def is_restore_ok(self): 1021 def is_restore_ok(self):
1019 """ Is the user allowed to restore this item? 1022 """ Is the user allowed to restore this item?
1020 """ 1023 """
1021 perm = self._db.security.hasPermission 1024 perm = self._db.security.hasPermission
1024 1027
1025 def is_view_ok(self): 1028 def is_view_ok(self):
1026 """ Is the user allowed to View this item? 1029 """ Is the user allowed to View this item?
1027 """ 1030 """
1028 perm = self._db.security.hasPermission 1031 perm = self._db.security.hasPermission
1029 if perm('Web Access', self._client.userid) and perm('View', 1032 if perm('Web Access', self._client.userid) and perm(
1030 self._client.userid, self._classname, itemid=self._nodeid): 1033 'View', self._client.userid, self._classname,
1034 itemid=self._nodeid):
1031 return 1 1035 return 1
1032 return self.is_edit_ok() 1036 return self.is_edit_ok()
1033 1037
1034 def is_only_view_ok(self): 1038 def is_only_view_ok(self):
1035 """ Is the user only allowed to View (ie. not Edit) this item? 1039 """ Is the user only allowed to View (ie. not Edit) this item?
1036 """ 1040 """
1037 return self.is_view_ok() and not self.is_edit_ok() 1041 return self.is_view_ok() and not self.is_edit_ok()
1038 1042
1039 def __repr__(self): 1043 def __repr__(self):
1040 return '<HTMLItem(0x%x) %s %s>' % (id(self), self._classname, 1044 return '<HTMLItem(0x%x) %s %s>' % (id(self), self._classname,
1041 self._nodeid) 1045 self._nodeid)
1042 1046
1043 def __getitem__(self, item): 1047 def __getitem__(self, item):
1044 """ return an HTMLProperty instance 1048 """ return an HTMLProperty instance
1045 this now can handle transitive lookups where item is of the 1049 this now can handle transitive lookups where item is of the
1046 form x.y.z 1050 form x.y.z
1071 # look up the correct HTMLProperty class 1075 # look up the correct HTMLProperty class
1072 htmlprop = None 1076 htmlprop = None
1073 for klass, htmlklass in propclasses: 1077 for klass, htmlklass in propclasses:
1074 if isinstance(prop, klass): 1078 if isinstance(prop, klass):
1075 htmlprop = htmlklass(self._client, self._classname, 1079 htmlprop = htmlklass(self._client, self._classname,
1076 self._nodeid, prop, items[0], value, self._anonymous) 1080 self._nodeid, prop, items[0],
1081 value, self._anonymous)
1077 if htmlprop is not None: 1082 if htmlprop is not None:
1078 if has_rest: 1083 if has_rest:
1079 if isinstance(htmlprop, MultilinkHTMLProperty): 1084 if isinstance(htmlprop, MultilinkHTMLProperty):
1080 return [h[items[1]] for h in htmlprop] 1085 return [h[items[1]] for h in htmlprop]
1081 return htmlprop[items[1]] 1086 return htmlprop[items[1]]

Roundup Issue Tracker: http://roundup-tracker.org/