def __get_path__(self, parent_pattern): if parent_pattern: # return "/{0}{1}".format(self.name_parent, simplify_regex(self.pattern.regex.pattern)) return "/{0}{1}".format( self.name_parent, simplify_regex(self.pattern.pattern.regex.pattern)) return simplify_regex(self.pattern.regex.pattern)
def extract_url_data(urls, prefix=''): views = [] for url in urls: if isinstance(url, RegexURLPattern): views.append({ 'view': extract_view_info(url.callback), 'url': simplify_regex(prefix + url.regex.pattern) }) if isinstance(url, RegexURLResolver): views += extract_url_data(url.url_patterns, prefix=simplify_regex(prefix + url.regex.pattern)) return sorted(views, key=lambda view: view['url'])
def __init__(self, pattern, regex_pattern=None,is_root=True): self.pattern = pattern self.callback = pattern.callback # self.name = pattern.name self.docstring = self.__get_docstring__() self.name_parent = simplify_regex(regex_pattern).strip('/').split("/")[0].strip() if not is_root else "root" self.path = simplify_regex(regex_pattern) self.allowed_methods = self.__get_allowed_methods__() # self.view_name = pattern.callback.__name__ self.errors = None self.fields = self.__get_serializer_fields__() self.fields_json = self.__get_serializer_fields_json__() self.permissions = self.__get_permissions_class__()
def simplify_regex(pattern): """ Do the same as django.contrib.admindocs.views.simplify_regex but with our improved regex. """ if django.VERSION[1] > 10: original_regex = admindocs_utils.unnamed_group_matcher admindocs_utils.unnamed_group_matcher = non_named_group_matcher result = admindocs_views.simplify_regex(pattern) admindocs_utils.unnamed_group_matcher = original_regex else: original_regex = admindocs_views.non_named_group_matcher admindocs_views.non_named_group_matcher = non_named_group_matcher result = admindocs_views.simplify_regex(pattern) admindocs_views.non_named_group_matcher = original_regex return result
def __get_path(self, parent_regex): """ Формирует и возвращает полный путь до поинта относительно урлов. :param parent_regex: Родительский урл. :type parent_regex: RegexpURL :return: Полный путь относительно роутера до поинта. :rtype: str """ if parent_regex: return '/{0}{1}'.format(self.name_parent, simplify_regex(self.pattern.regex.pattern)) return simplify_regex(self.pattern.regex.pattern)
def _add_test_methods(mcs, attrs, urlpatterns): # loop through every URL pattern for index, (func, regex, url_name) in enumerate( extract_views_from_urlpatterns(urlpatterns)): if 'module_exclude' not in attrs: attrs['module_exclude'] = None if attrs['module_exclude'] is not None: if func.__module__.startswith("%s." % attrs['module_exclude']): continue elif func.__module__ == attrs['module_exclude']: continue else: pass if func.__module__.startswith("%s." % attrs['module']): pass elif func.__module__ == attrs['module']: pass else: continue if hasattr(func, '__name__'): func_name = func.__name__ elif hasattr(func, '__class__'): func_name = '%s()' % func.__class__.__name__ else: func_name = re.sub(r' at 0x[0-9a-f]+', '', repr(func)) url_pattern = smart_text(simplify_regex(regex)) name = '_'.join( [ 'test', func.__module__.replace('.', '_'), slugify('%s' % func_name), ] + slugify( url_pattern.replace('/', '_') or 'root' ).replace('_', ' ').split(), ) url = url_pattern for key, value in attrs['variables'].items(): url = url.replace('<%s>' % key, value) # bail out if we don't know how to visit this URL properly testfunc = unittest.skipIf( any( re.search(stop_pattern, url) for stop_pattern in [ r'<.*>', ] ), 'URL pattern %r contains stop pattern.' % url, )( make_test_get_function(name, url, url_pattern), ) attrs[name] = testfunc
def handle(self, *args, **options): if args: appname, = args namespace = options.get("namespace", "") if settings.ADMIN_FOR: settings_modules = [__import__(m, {}, {}, [""]) for m in settings.ADMIN_FOR] else: settings_modules = [settings] views = {} for settings_mod in settings_modules: try: urlconf = __import__(settings_mod.ROOT_URLCONF, {}, {}, [""]) except Exception, e: if options.get("traceback", None): import traceback traceback.print_exc() print style.ERROR("Error occurred while trying to load %s: %s" % (settings_mod.ROOT_URLCONF, str(e))) continue view_functions = extract_views_from_urlpatterns(urlconf.urlpatterns) for (func, regex, url_name) in view_functions: if url_name: views[url_name] = simplify_regex(regex)
def handle(self, *args, **options): if args: appname, = args style = color_style() if settings.ADMIN_FOR: settings_modules = [__import__(m, {}, {}, ['']) for m in settings.ADMIN_FOR] else: settings_modules = [settings] views = [] for settings_mod in settings_modules: try: urlconf = __import__(settings_mod.ROOT_URLCONF, {}, {}, ['']) except Exception, e: if options.get('traceback', None): import traceback traceback.print_exc() print style.ERROR("Error occurred while trying to load %s: %s" % (settings_mod.ROOT_URLCONF, str(e))) continue view_functions = extract_views_from_urlpatterns(urlconf.urlpatterns) for (func, regex, url_name) in view_functions: if hasattr(func, '__name__'): func_name = func.__name__ elif hasattr(func, '__class__'): func_name = '%s()' % func.__class__.__name__ else: func_name = re.sub(r' at 0x[0-9a-f]+', '', repr(func)) views.append("%(url)s\t%(module)s.%(name)s\t%(url_name)s" % {'name': style.MODULE_NAME(func_name), 'module': style.MODULE(func.__module__), 'url_name': style.URL_NAME(url_name or ''), 'url': style.URL(simplify_regex(regex))})
def extract_views_from_urlpatterns(self, urlpatterns, base='', namespace=None): views = [] for pattern in urlpatterns: if isinstance(pattern, RegexURLPattern): view = pattern.callback view_class = getattr(view, 'view_class', None) expose_js_viewname = view in viewnames_exposed_js or view_class in viewnames_exposed_js name = '{0}:{1}'.format( namespace, pattern.name) if namespace else pattern.name if expose_js_viewname and name: views.append( (name, simplify_regex(base + pattern.regex.pattern))) elif isinstance(pattern, RegexURLResolver): patterns = pattern.url_patterns if namespace and pattern.namespace: _namespace = '{0}:{1}'.format(namespace, pattern.namespace) else: _namespace = (pattern.namespace or namespace) views.extend( self.extract_views_from_urlpatterns(patterns, base + pattern.regex.pattern, namespace=_namespace)) else: raise TypeError( "%s does not appear to be a urlpattern object" % pattern) return views
def __assemble_endpoint_data__(pattern, prefix="", filter_path=None): """Create a dictionary for matched API urls. Args: pattern: pattern to parse. prefix: API path prefix (used by recursion). filter_path: Returns: """ path = simplify_regex(prefix + pattern.pattern.regex.pattern) if filter_path is not None: if re.match("^/?%s(/.*)?$" % re.escape(filter_path), path) is None: return None path = path.replace("<", "{").replace(">", "}") return { "url": path, "view": pattern.lookup_str, "name": pattern.default_args["name"], "enable_by_default": pattern.default_args["enable_by_default"], }
def __get_resource_data(self, pattern, prefix, callback): path = simplify_regex(pattern.regex.pattern) path = path.replace('<', '{').replace('>', '}') full_path = prefix.rstrip('/') + path methods = [] for method_name in HTTP_METHODS: if method_name == 'OPTIONS': continue method = getattr(callback, method_name.lower(), None) if method is None: continue title, docstring = self.__split_doc(method.__doc__ or '', path=path) if not title: title = '{} {}'.format(method_name, path) methods.append({ 'verb': method_name, 'path': full_path, 'title': title, 'anchor': self.__title_to_anchor(title), 'doc': self.__format_doc(docstring, { 'path': full_path, 'method': method_name, }), }) return { 'path': full_path, 'methods': methods, 'section': getattr(callback, 'doc_section', None), }
def get_url_info(self, urlpatterns=None): """ return a dict-list of the current used url patterns """ if urlpatterns is None: urlpatterns = self._get_root_urlpatterns() view_functions = self._extract_views_from_urlpatterns(urlpatterns) url_info = [] for (func, regex, url_name) in view_functions: if hasattr(func, '__name__'): func_name = func.__name__ elif hasattr(func, '__class__'): func_name = '%s()' % func.__class__.__name__ else: func_name = re.sub(r' at 0x[0-9a-f]+', '', repr(func)) url = simplify_regex(regex) url_info.append({ 'func_name': func_name, 'module': func.__module__, 'url_name': url_name, 'regex': regex, 'url': url }) return url_info
def _add_test_methods(mcs, attrs, urlpatterns): # loop through every URL pattern for index, (func, regex, url_name) in enumerate(extract_views_from_urlpatterns(urlpatterns)): if func.__module__.startswith("%s." % attrs["module"]): pass elif func.__module__ == attrs["module"]: pass else: continue if hasattr(func, "__name__"): func_name = func.__name__ elif hasattr(func, "__class__"): func_name = "%s()" % func.__class__.__name__ else: func_name = re.sub(r" at 0x[0-9a-f]+", "", repr(func)) url_pattern = smart_text(simplify_regex(regex)) name = "_".join( ["test", func.__module__.replace(".", "_"), slugify("%s" % func_name)] + slugify(url_pattern.replace("/", "_") or "root").replace("_", " ").split() ) url = url_pattern for key, value in attrs["variables"].items(): url = url.replace("<%s>" % key, value) # bail out if we don't know how to visit this URL properly testfunc = unittest.skipIf( any(re.search(stop_pattern, url) for stop_pattern in [r"<.*>"]), "URL pattern %r contains stop pattern." % url, )(make_test_get_function(name, url, url_pattern)) attrs[name] = testfunc
def __assemble_endpoint_data__(self, pattern, prefix='', filter_path=None): """ Creates a dictionary for matched API urls pattern -- the pattern to parse prefix -- the API path prefix (used by recursion) """ callback = self.__get_pattern_api_callback__(pattern) if callback is None or self.__exclude_router_api_root__(callback): return path = simplify_regex(prefix + pattern.regex.pattern) if filter_path is not None: if re.match('^/?%s(/.*)?$' % re.escape(filter_path), path) is None: return None path = path.replace('<', '{').replace('>', '}') path = self.__make_relative__(path) if self.__exclude_format_endpoints__(path): return return { 'path': path, 'pattern': pattern, 'callback': callback, }
def get_path_from_regex(self, path_regex): """ Given a URL conf regex, return a URI template string. """ path = simplify_regex(path_regex) path = path.replace('<', '{').replace('>', '}') return path
def gather_endpoint_data(self, pattern, prefix='', filter_path=None): """ Creates a dictionary for matched API urls pattern -- the pattern to parse prefix -- the API path prefix (used by recursion) """ callback = self.filter_api_view_callbacks(pattern) if callback: path = simplify_regex(prefix + pattern.regex.pattern) if self.is_router_api_root(callback) or filter_path and filter_path not in path: return path = path.replace('<', '{').replace('>', '}') # These additional RegexURLPatterns paths are duplicated by DRF and not needed. if '.{format}' in path: return return { 'path': path, 'pattern': pattern, 'callback': callback, }
def get_all_views(): if settings.ADMIN_FOR: settings_modules = [__import__(m, {}, {}, ['']) for m in settings.ADMIN_FOR] else: settings_modules = [settings] views = [] for settings_mod in settings_modules: try: urlconf = __import__(settings_mod.ROOT_URLCONF, {}, {}, ['']) except: continue view_functions = extract_views_from_urlpatterns(urlconf.urlpatterns) for (func, regex, url_name) in view_functions: if hasattr(func, '__name__'): func_name = func.__name__ somemodule = importlib.import_module(func.__module__) klass = getattr(somemodule, func_name, None) if klass and hasattr(klass, 'permission_required'): try: perm = Permission.objects.get(codename=klass.permission_required.split('.')[1]) except: perm = None if perm: views.append({ 'name': func_name, 'module': func.__module__, 'permission_codename': perm.codename, 'permission_applabel': perm.content_type.app_label, 'url': simplify_regex(regex), }) return views
def __assemble_endpoint_data__(self, pattern, prefix='', filter_path=None): """ Creates a dictionary for matched API urls pattern -- the pattern to parse prefix -- the API path prefix (used by recursion) """ callback = self.__get_pattern_api_callback__(pattern) if callback is None or self.__exclude_router_api_root__(callback): return # Ugly hack to get version from regex regex_path = prefix + pattern.regex.pattern regex_path = regex_path.replace(r'(\.0)?', r'\.0') regex_path = re.sub(r'v\(\?P\<version\>(\d+\\\.\d+)\)', r'v\1', regex_path) path = simplify_regex(regex_path) if filter_path is not None: if re.match('^/?%s(/.*)?$' % re.escape(filter_path), path) is None: return None path = path.replace('<', '{').replace('>', '}') if self.__exclude_format_endpoints__(path): return return { 'path': path, 'pattern': pattern, 'callback': callback, }
def __get_path_from_regex(self, path_regex): """ 给定URL conf正则表达式,返回URI模板字符串 """ path = simplify_regex(path_regex) path = re.sub(self._PATH_PARAMETER_COMPONENT_RE, r'{\g<parameter>}', path) return path
def handle(self, *args, **options): if args: appname, = args style = color_style() if settings.ADMIN_FOR: settings_modules = [ __import__(m, {}, {}, ['']) for m in settings.ADMIN_FOR ] else: settings_modules = [settings] views = [] for settings_mod in settings_modules: urlconf = __import__(settings_mod.ROOT_URLCONF, {}, {}, ['']) view_functions = extract_views_from_urlpatterns( urlconf.urlpatterns) for (func, regex) in view_functions: views.append( "%(url)s\t%(module)s.%(name)s" % { 'name': style.MODULE_NAME(func.__name__), 'module': style.MODULE(func.__module__), 'url': style.URL(simplify_regex(regex)) }) return "\n".join([v for v in views])
def __assemble_endpoint_data__(self, pattern, prefix='', filter_path=None): """ Creates a dictionary for matched API urls pattern -- the pattern to parse prefix -- the API path prefix (used by recursion) """ callback = self.__get_pattern_api_callback__(pattern) if callback is None or self.__exclude_router_api_root__(callback): return path = simplify_regex(prefix + pattern.regex.pattern) if filter_path is not None: if filter_path not in path: return None path = path.replace('<', '{').replace('>', '}') if self.__exclude_format_endpoints__(path): return return { 'path': path, 'pattern': pattern, 'callback': callback, }
def index(request): urlconf = __import__(settings.ROOT_URLCONF, {}, {}, ['urlpatterns']) view_functions = extract_views_from_urlpatterns(urlconf.urlpatterns) resultant_routes = {} for (func, regex, name) in view_functions: if name in settings.EXPOSED_ROUTES: simplified_regex = simplify_regex(regex) resultant_routes[name] = {} resultant_routes[name]['pattern'] = simplified_regex resultant_routes[name]['parameters'] = re.findall('<(.*)>', simplified_regex) template = loader.get_template('django_js_routing/routes.js') context = RequestContext(request, { 'routes': json.dumps(resultant_routes) }) response = HttpResponse( template.render(context), content_type='application/javascript' ) return response
def get_url_info(self): """ return a dict-list of the current used url patterns """ urlconf = __import__(settings.ROOT_URLCONF, {}, {}, ['']) view_functions = self._extract_views_from_urlpatterns(urlconf.urlpatterns) url_info = [] for (func, regex, url_name) in view_functions: if hasattr(func, '__name__'): func_name = func.__name__ elif hasattr(func, '__class__'): func_name = '%s()' % func.__class__.__name__ else: func_name = re.sub(r' at 0x[0-9a-f]+', '', repr(func)) url = simplify_regex(regex) url_info.append({ 'func_name': func_name, 'module': func.__module__, 'url_name': url_name, 'regex': regex, 'url': url }) return url_info
def get_path_from_regex(self, path_regex): """ Given a URL conf regex, return a URI template string. """ path = simplify_regex(path_regex) path = path.replace("<", "{").replace(">", "}") return path
def view_index(request): if not utils.docutils_is_available: return missing_docutils_page(request) view_dict = {} view_functions = extract_views_from_urlpatterns(api1_urls.urlpatterns) + extract_views_from_urlpatterns( oauth_urls.urlpatterns ) for (func, regex) in view_functions: view = { "name": getattr(func, "__name__", func.__class__.__name__), "module": func.__module__, "url": simplify_regex(regex), } if view["name"] in ["authorize", "access_token", "request_token"]: view["url"] = "/oauth%s" % view["url"] view["group"] = "oauth" else: view["group"] = view["url"].split("/")[1] view["url"] = "/1" + view["url"] if view_dict.has_key(view["group"]): view_dict[view["group"]].append(view) else: view_dict[view["group"]] = [view] return render_to_response( "doc/view_index.tpl", {"root_path": get_root_path(), "view_dict": view_dict}, context_instance=RequestContext(request), )
def __init__(self, pattern, parent_pattern=tuple(), drf_router=None): self.drf_router = drf_router self.pattern = pattern self.callback = pattern.callback # self.name = pattern.name self.docstring = self.__get_docstring__() self.name_parent = '/'.join([ simplify_regex(p.regex.pattern).strip('/') for p in parent_pattern ]) self.path = self.__get_path__(parent_pattern) self.method_action_map = {} self.allowed_methods = self.__get_allowed_methods__() # self.view_name = pattern.callback.__name__ self.errors = None self.serializer_class = self.__get_serializer_class__() if self.serializer_class: self.serializer = self.__get_serializer__(self.serializer_class) self.fields = self.__get_serializer_fields__(self.serializer) self.fields_json = self.__get_serializer_fields_json__(self.fields) # Can only be usefule if the Viewset uses queryparams_serializer mixin self.queryparams_serializer_class = self.__get_queryparams_serializer_class__( ) if self.queryparams_serializer_class: self.queryparams_serializer = self.__get_serializer__( self.queryparams_serializer_class) self.queryparams_fields = self.__get_serializer_fields__( self.queryparams_serializer) self.queryparms_fields_json = self.__get_serializer_fields_json__( self.queryparams_fields) self.permissions = self.__get_permissions_class__()
def __assemble_endpoint_data__(self, pattern, prefix='', filter_path=None): """ Creates a dictionary for matched API urls pattern -- the pattern to parse prefix -- the API path prefix (used by recursion) """ callback = self.__get_pattern_api_callback__(pattern) if callback is None or self.__exclude_router_api_root__(callback): return path = simplify_regex(prefix + pattern.regex.pattern) if filter_path is not None: filter_path = filter_path.rstrip('/') + '/' if filter_path not in path: return None path = path.replace('<', '{').replace('>', '}') if self.__exclude_format_endpoints__(path): return return { 'path': path, 'pattern': pattern, 'callback': callback, }
def handle(self, *args, **options): if args: appname, = args style = color_style() if settings.ADMIN_FOR: settings_modules = [__import__(m, {}, {}, ['']) for m in settings.ADMIN_FOR] else: settings_modules = [settings] views = [] for settings_mod in settings_modules: try: urlconf = __import__(settings_mod.ROOT_URLCONF, {}, {}, ['']) except Exception, e: if options.get('traceback', None): import traceback self.stderr.write(traceback.format_exc() + "\n") self.stderr.write( style.ERROR("Error occurred while trying to load %s: %s\n" % (settings_mod.ROOT_URLCONF, str(e)))) continue view_functions = \ extract_views_from_urlpatterns(urlconf.urlpatterns) for (func, regex) in view_functions: func_name = hasattr(func, '__name__') and \ func.__name__ or repr(func) views.append("%(url)s\t%(module)s.%(name)s" % {'name': style.MODULE_NAME(func_name), 'module': style.MODULE( getattr(func, '__module__', '<no module>')), 'url': style.URL(simplify_regex(regex))})
def handle(self, *args, **options): ignored_modules = args if args else DEFAULT_IGNORED_MODULES views = [] urlconf = __import__(settings.ROOT_URLCONF, {}, {}, ['']) view_functions = extract_views_from_urlpatterns(urlconf.urlpatterns, ignored_modules=ignored_modules) for (func, regex, url_name) in view_functions: # Extract real function from partial if isinstance(func, functools.partial): func = func.func decorators_and_mixins = get_decorators(func) + get_mixins(func, ignored_modules=ignored_modules) views.append("{url}||{module}||{decorators}".format( module='{0}.{1}'.format(func.__module__, get_func_name(func)), url=simplify_regex(regex), decorators=', '.join(decorators_and_mixins) )) info = ( "Decorators lists are not comprehensive and do not take account of other patching.\n" "Decorators for methods of class-based views are not listed." ) table = display_as_table(views) return "\n{0}\n{1}".format(table, info)
def view_index(request): if not utils.docutils_is_available: return missing_docutils_page(request) view_dict = {} view_functions = extract_views_from_urlpatterns(api1_urls.urlpatterns) + \ extract_views_from_urlpatterns(oauth_urls.urlpatterns) for (func, regex) in view_functions: view = { 'name': getattr(func, '__name__', func.__class__.__name__), 'module': func.__module__, 'url': simplify_regex(regex) } if view['name'] in ['authorize', 'access_token', 'request_token']: view['url'] = "/oauth%s" % view['url'] view['group'] = 'oauth' else: view['group'] = view['url'].split('/')[1] view['url'] = "/1" + view['url'] if view_dict.has_key(view['group']): view_dict[view['group']].append(view) else: view_dict[view['group']] = [view] return render_to_response( 'doc/view_index.tpl', { 'root_path': get_root_path(), 'view_dict': view_dict }, context_instance=RequestContext(request) )
def __init__(self, pattern, parent_pattern=None, drf_router=None): self.drf_router = drf_router or [] if not isinstance(self.drf_router, (list, tuple)): self.drf_router = [self.drf_router] self.pattern = pattern self.callback = pattern.callback self.docstring = self.__get_docstring__() if parent_pattern: self.name_parent = parent_pattern.namespace or parent_pattern.app_name or \ simplify_regex(parent_pattern.regex.pattern).replace('/', '-') self.name = self.name_parent if hasattr(pattern.callback, 'cls') and issubclass( pattern.callback.cls, ModelViewSet): self.name = '%s (RESTful)' % self.name_parent else: self.name_parent = '' self.name = '' # self.labels = (self.name_parent, self.name, slugify(self.name)) self.labels = dict(parent=self.name_parent, name=self.name) self.path = self.__get_path__(parent_pattern) self.allowed_methods = self.__get_allowed_methods__() self.errors = None self.serializer_class = self.__get_serializer_class__() if self.serializer_class: self.serializer = self.__get_serializer__() self.fields = self.__get_serializer_fields__() self.fields_json = self.__get_serializer_fields_json__() self.permissions = self.__get_permissions_class__()
def __init__(self, pattern, parent_pattern=None): # XXX: Hotfix for openstack app docs. app_name = pattern.callback.cls.__module__.split('.')[-2] app_name = app_name.replace('waldur_openstack', 'openstack') app_name = app_name.replace('waldur_auth_social', 'nodeconductor_auth') conf = apps.get_app_config(app_name) self.pattern = pattern self.callback = pattern.callback self.docstring = getdoc(self.callback.cls) self.name_parent = simplify_regex(parent_pattern.regex.pattern).replace('/', '') if parent_pattern else None self.path = self.get_path(parent_pattern) self.name = conf.verbose_name self.app = conf.label cls = self.callback.cls action = self.path.split('/')[-2] self.actions = [m for m in dir(cls) if hasattr(getattr(cls, m), 'bind_to_methods')] self.action = action if action in self.actions else None if self.action: self.methods = [m.upper() for m in reduce(getattr, [action, 'bind_to_methods'], cls)] else: self.methods = [] for method, action in self.METHODS: if method in self.methods: continue if hasattr(cls, action) or hasattr(cls, method.lower()): self.methods.append(method) self.VIEWS[pattern.name] = self.path
def test_simplify_regex(self): tests = ( ('^a', '/a'), ('^(?P<a>\w+)/b/(?P<c>\w+)/$', '/<a>/b/<c>/'), ('^(?P<a>\w+)/b/(?P<c>\w+)$', '/<a>/b/<c>'), ) for pattern, output in tests: self.assertEqual(simplify_regex(pattern), output)
def __get_path__(self, endpoint): """ Gets the endpoint path based on the regular expression pattern of the URL pattern. Cleans out the regex characters and replaces with RESTful URL descriptors """ #return simplify_regex(endpoint.regex.pattern) return simplify_regex(endpoint.__path)
def get_path_from_regex(self, path_regex): """ Given a URL conf regex, return a URI template string. """ path = simplify_regex(path_regex) # Strip Django 2.0 convertors as they are incompatible with uritemplate format return re.sub(_PATH_PARAMETER_COMPONENT_RE, r'{\g<parameter>}', path)
def test_simplify_regex(self): tests = ( (r"^a", "/a"), (r"^(?P<a>\w+)/b/(?P<c>\w+)/$", "/<a>/b/<c>/"), (r"^(?P<a>\w+)/b/(?P<c>\w+)$", "/<a>/b/<c>"), ) for pattern, output in tests: self.assertEqual(simplify_regex(pattern), output)
def _get_pattern_name(pattern): if hasattr(pattern, '_regex'): return simplify_regex(pattern._regex)[1:] if hasattr(pattern, 'pattern'): _pattern = pattern.pattern if hasattr(_pattern, '_route'): return str(_pattern._route) return ''
def _get_complete_path(pattern, prefix=None): try: regex = pattern._regex if hasattr( pattern, "_regex") else pattern.pattern._regex except: regex = pattern._route if hasattr( pattern, "_route") else pattern.pattern._route return prefix + simplify_regex(regex)[1:]
def test_simplify_regex(self): tests = ( (r'^a', '/a'), (r'^(?P<a>\w+)/b/(?P<c>\w+)/$', '/<a>/b/<c>/'), (r'^(?P<a>\w+)/b/(?P<c>\w+)$', '/<a>/b/<c>'), ) for pattern, output in tests: self.assertEqual(simplify_regex(pattern), output)
def handle(self, *args, **options): if args: appname, = args style = color_style() if settings.ADMIN_FOR: settings_modules = [__import__(m, {}, {}, ['']) for m in settings.ADMIN_FOR] else: settings_modules = [settings] language = options.get('language', None) if language is not None: activate(language) decorator = options.get('decorator') if decorator is None: decorator = 'login_required' format_style = options.get('format_style', 'dense') if format_style not in FMTR: raise Exception("Format style '%s' does not exist. Options: %s" % (format_style, FMTR.keys())) fmtr = FMTR[format_style] views = [] for settings_mod in settings_modules: try: urlconf = __import__(settings_mod.ROOT_URLCONF, {}, {}, ['']) except Exception as e: if options.get('traceback', None): import traceback traceback.print_exc() print(style.ERROR("Error occurred while trying to load %s: %s" % (settings_mod.ROOT_URLCONF, str(e)))) continue view_functions = extract_views_from_urlpatterns(urlconf.urlpatterns) for (func, regex, url_name) in view_functions: if hasattr(func, '__name__'): func_name = func.__name__ elif hasattr(func, '__class__'): func_name = '%s()' % func.__class__.__name__ else: func_name = re.sub(r' at 0x[0-9a-f]+', '', repr(func)) func_globals = func.__globals__ if six.PY3 else func.func_globals views.append(fmtr % { 'name': style.MODULE_NAME(func_name), 'module': style.MODULE(func.__module__), 'url_name': style.URL_NAME(url_name or ''), 'url': style.URL(simplify_regex(regex)), 'decorator': decorator if decorator in func_globals else '', }) if not options.get('unsorted', False): views = sorted(views) return "\n".join([v for v in views]) + "\n"
def _get_complete_path(pattern, prefix=None): try: if hasattr(pattern, "_regex"): regex = pattern._regex elif hasattr(pattern.pattern, "_regex"): regex = pattern.pattern._regex else : regex = str(pattern.pattern) except: regex = "" return prefix + simplify_regex(regex)
def get_path_from_regex(self, path_regex): """ Given a URL conf regex, return a URI template string. """ # ???: Would it be feasible to adjust this such that we generate the # path, plus the kwargs, plus the type from the convertor, such that we # could feed that straight into the parameter schema object? path = simplify_regex(path_regex) # Strip Django 2.0 convertors as they are incompatible with uritemplate format return re.sub(_PATH_PARAMETER_COMPONENT_RE, r'{\g<parameter>}', path)
def _add_test_methods(mcs, attrs, urlpatterns): # loop through every URL pattern for index, (func, regex, url_name) in enumerate( extract_views_from_urlpatterns(urlpatterns)): if 'module_exclude' not in attrs: attrs['module_exclude'] = None if attrs['module_exclude'] is not None: if func.__module__.startswith("%s." % attrs['module_exclude']): continue elif func.__module__ == attrs['module_exclude']: continue else: pass if func.__module__.startswith("%s." % attrs['module']): pass elif func.__module__ == attrs['module']: pass else: continue if hasattr(func, '__name__'): func_name = func.__name__ elif hasattr(func, '__class__'): func_name = '%s()' % func.__class__.__name__ else: func_name = re.sub(r' at 0x[0-9a-f]+', '', repr(func)) url_pattern = smart_text(simplify_regex(regex)) name = '_'.join([ 'test', func.__module__.replace('.', '_'), slugify('%s' % func_name), ] + slugify(url_pattern.replace('/', '_') or 'root').replace( '_', ' ').split(), ) url = url_pattern for key, value in attrs['variables'].items(): url = url.replace('<%s>' % key, value) # bail out if we don't know how to visit this URL properly testfunc = unittest.skipIf( any( re.search(stop_pattern, url) for stop_pattern in [ r'<.*>', ]), 'URL pattern %r contains stop pattern.' % url, )(make_test_get_function(name, url, url_pattern), ) attrs[name] = testfunc
def _get_views(urlpatterns=None, base_url=''): """ Recursively fetch all views in the specified urlpatterns. If urlpatterns is not specified, uses the `PERMISSIONS_AUDITOR_ROOT_URLCONF` setting, which by default is the value of `ROOT_URLCONF` in your project settings. Returns a list of `View` namedtuples. """ views = [] if urlpatterns is None: root_urlconf = import_string( _get_setting('PERMISSIONS_AUDITOR_ROOT_URLCONF')) urlpatterns = root_urlconf.urlpatterns parser = ViewParser() for pattern in urlpatterns: if isinstance(pattern, RoutePattern) or isinstance( pattern, URLResolver): if pattern.namespace in NAMESPACE_BLACKLIST: continue # Recursively fetch patterns views.extend( _get_views(pattern.url_patterns, base_url + str(pattern.pattern))) elif isinstance(pattern, URLPattern) or isinstance( pattern, RegexPattern): view = pattern.callback # If this is a CBV, use the actual class instead of the as_view() classmethod. view = getattr(view, 'view_class', view) view = getattr(view, 'cls', view) full_view_path = '{}.{}'.format(view.__module__, view.__name__) if full_view_path in VIEW_BLACKLIST or view.__module__ in MODULE_BLACKLIST: continue permissions, login_required, docstring = parser.parse(view) views.append( ViewDetails._make([ view.__module__, view.__name__, simplify_regex(base_url + str(pattern.pattern)), permissions, login_required, docstring ])) return views
def get_views(urlpatterns, base=''): views = OrderedDict() for pattern in urlpatterns: if isinstance(pattern, RegexURLResolver): views.update(get_views( urlpatterns=pattern.url_patterns, base=base + pattern.regex.pattern, )) elif isinstance(pattern, RegexURLPattern): url = base + pattern.regex.pattern url = URL_PARAMETER_PATTERN.sub('{\g<param>}', simplify_regex(url)) views[url] = pattern.callback return views
def __init__(self, pattern, parent_pattern=None): self.pattern = pattern self.callback = pattern.callback # self.name = pattern.name self.docstring = self.__get_docstring__() self.name_parent = simplify_regex(parent_pattern.regex.pattern).strip('/') if parent_pattern else None self.path = self.__get_path__(parent_pattern) self.allowed_methods = self.__get_allowed_methods__() # self.view_name = pattern.callback.__name__ self.errors = None self.fields = self.__get_serializer_fields__() self.fields_json = self.__get_serializer_fields_json__() self.permissions = self.__get_permissions_class__()
def parse_tree(self, urlpatterns, parent_node, prefix=''): for pattern in urlpatterns: if isinstance(pattern, RegexURLResolver): child_node_name = simplify_regex(pattern._regex).strip('/') if pattern._regex else "" self.parse_tree( urlpatterns=pattern.url_patterns, parent_node=parent_node[child_node_name] if child_node_name else parent_node, prefix='%s/%s' % (prefix, child_node_name) ) elif isinstance(pattern, RegexURLPattern) and self._is_drf_pattern(pattern): api_endpoint = Endpoint(pattern, prefix) parent_node[api_endpoint.name] = api_endpoint
def test_simplify_regex(self): tests = ( (r'^a', '/a'), (r'^(?P<a>\w+)/b/(?P<c>\w+)/$', '/<a>/b/<c>/'), (r'^(?P<a>\w+)/b/(?P<c>\w+)$', '/<a>/b/<c>'), (r'^(?P<a>\w+)/b/(\w+)$', '/<a>/b/<var>'), (r'^(?P<a>\w+)/b/((x|y)\w+)$', '/<a>/b/<var>'), (r'^(?P<a>(x|y))/b/(?P<c>\w+)$', '/<a>/b/<c>'), (r'^(?P<a>(x|y))/b/(?P<c>\w+)ab', '/<a>/b/<c>ab'), (r'^(?P<a>(x|y)(\(|\)))/b/(?P<c>\w+)ab', '/<a>/b/<c>ab'), ) for pattern, output in tests: self.assertEqual(simplify_regex(pattern), output)
def _get_urls(self): urls = [] if settings.ADMIN_FOR: settings_modules = [__import__(m, {}, {}, ['']) for m in settings.ADMIN_FOR] else: settings_modules = [settings] for settings_mod in settings_modules: try: urlconf = __import__(settings_mod.ROOT_URLCONF, {}, {}, ['']) except Exception as e: continue view_functions = extract_views_from_urlpatterns(urlconf.urlpatterns) for view_function in view_functions: urls.append(simplify_regex(view_function[1])) return urls
def views_to_graph(views, diag=True, colorful=True, with_label=True): """ Retorna um grafo na linguagem dot a partir do retorno da função get_view_func_regex_url_name """ graph = 'blockdiag' if diag else 'graph' urls, colors = [], [] def get_color(): while True: color = to_hex((randint(5, 200), randint(5, 200), randint(5, 200))) if color in colors: continue colors.append(color) return color for index, (v, r, n) in enumerate(views): if colorful: if index > 0: color = 'color="#%s"' % ''.join(get_color()) else: color = 'color="#ffffff"' if with_label: if hasattr(v, '__name__'): label = v.__name__ else: label = v.__class__.__name__ label = 'label="%s"' % label if not colorful and not with_label: opts = '' elif colorful and not with_label: opts = ' [%s]' % color elif with_label and not colorful: opts = ' [%s]' % label else: opts = ' [%s, %s]' % (color, label) u = '"/%s' % simplify_regex(r).replace('/', '" -> "') if u.endswith(' -> "'): u = u[0:-5] + '%s;' % opts else: u += '"%s;' % opts urls.append(" %s" % u) return '%s {\n%s\n}' % (graph, '\n'.join(urls))