| 791 | self._resources.append(resource) |
| 792 | |
| 793 | def add_resource(self, path, *, name=None): |
| 794 | if not path.startswith('/'): |
| 795 | raise ValueError("path should be started with /") |
| 796 | if not ('{' in path or '}' in path or self.ROUTE_RE.search(path)): |
| 797 | resource = PlainResource(path, name=name) |
| 798 | self._reg_resource(resource) |
| 799 | return resource |
| 800 | |
| 801 | pattern = '' |
| 802 | formatter = '' |
| 803 | for part in self.ROUTE_RE.split(path): |
| 804 | match = self.DYN.match(part) |
| 805 | if match: |
| 806 | pattern += '(?P<{}>{})'.format(match.group('var'), self.GOOD) |
| 807 | formatter += '{' + match.group('var') + '}' |
| 808 | continue |
| 809 | |
| 810 | match = self.DYN_WITH_RE.match(part) |
| 811 | if match: |
| 812 | pattern += '(?P<{var}>{re})'.format(**match.groupdict()) |
| 813 | formatter += '{' + match.group('var') + '}' |
| 814 | continue |
| 815 | |
| 816 | if '{' in part or '}' in part: |
| 817 | raise ValueError("Invalid path '{}'['{}']".format(path, part)) |
| 818 | |
| 819 | formatter += part |
| 820 | pattern += re.escape(part) |
| 821 | |
| 822 | try: |
| 823 | compiled = re.compile('^' + pattern + '$') |
| 824 | except re.error as exc: |
| 825 | raise ValueError( |
| 826 | "Bad pattern '{}': {}".format(pattern, exc)) from None |
| 827 | resource = DynamicResource(compiled, formatter, name=name) |
| 828 | self._reg_resource(resource) |
| 829 | return resource |
| 830 | |
| 831 | def add_route(self, method, path, handler, |
| 832 | *, name=None, expect_handler=None): |