|
1 |
| -import os |
| 1 | +import pathlib |
2 | 2 | import re
|
3 | 3 | from importlib import import_module
|
4 | 4 |
|
|
21 | 21 | TO_UNDERSCORES = re.compile("[/-]") # Slash and dash
|
22 | 22 |
|
23 | 23 |
|
24 |
| -def file_patterns(start_dir, append_slash=False): |
| 24 | +def file_patterns(start_dir: str, append_slash: bool = False, exclude: str = ""): |
25 | 25 | """
|
26 | 26 | Create urlpatterns from a directory structure
|
27 | 27 | """
|
28 | 28 | patterns = []
|
29 | 29 | start_dir_re = re.compile(f"^{start_dir}")
|
30 |
| - for root, dirs, files in os.walk(start_dir): |
31 |
| - # Reverse-sort the list so files that start with "<" go to the bottom |
32 |
| - # and regular files come to the top. This ensures hard-coded url params |
33 |
| - # always match before variable ones like <pk> and <slug> |
34 |
| - files = sorted(files, reverse=True) |
35 |
| - for file in files: |
36 |
| - if not file.endswith(".py"): |
37 |
| - continue |
| 30 | + files = pathlib.Path(start_dir).glob("**/*.py") |
| 31 | + # Reverse-sort the list so files that start with "<" go to the bottom |
| 32 | + # and regular files come to the top. This ensures hard-coded url params |
| 33 | + # always match before variable ones like <pk> and <slug> |
| 34 | + files = sorted(files, reverse=True, key=str) |
| 35 | + for file in files: |
| 36 | + if exclude and pathlib.Path.match(file, exclude): |
| 37 | + continue |
38 | 38 |
|
39 |
| - module_path = f"{root}/{file}".replace(".py", "").replace("/", ".") |
40 |
| - module = import_module(module_path) |
41 |
| - view_fn = getattr(module, "view", None) |
42 |
| - if not callable(view_fn): |
43 |
| - continue |
| 39 | + module_path = str(file).replace(".py", "").replace("/", ".") |
| 40 | + module = import_module(module_path) |
| 41 | + view_fn = getattr(module, "view", None) |
| 42 | + if not callable(view_fn): |
| 43 | + continue |
44 | 44 |
|
45 |
| - try: |
46 |
| - url = view_fn.url |
47 |
| - except AttributeError: |
48 |
| - url = "" if file == "__init__.py" else file.replace(".py", "") |
49 |
| - url = start_dir_re.sub("", f"{root}/{url}").strip("/") |
50 |
| - url = (url + "/") if append_slash and url != "" else url |
| 45 | + try: |
| 46 | + url = view_fn.url |
| 47 | + except AttributeError: |
| 48 | + url = "" if file.name == "__init__.py" else file.name.replace(".py", "") |
| 49 | + url = start_dir_re.sub("", f"{file.parent}/{url}").strip("/") |
| 50 | + url = (url + "/") if append_slash and url != "" else url |
51 | 51 |
|
52 |
| - try: |
53 |
| - urlname = view_fn.urlname |
54 |
| - except AttributeError: |
55 |
| - urlname = DISALLOWED_CHARS.sub("", TO_UNDERSCORES.sub("_", url)) |
| 52 | + try: |
| 53 | + urlname = view_fn.urlname |
| 54 | + except AttributeError: |
| 55 | + urlname = DISALLOWED_CHARS.sub("", TO_UNDERSCORES.sub("_", url)) |
56 | 56 |
|
57 |
| - patterns.append(path(url, view_fn, name=urlname)) |
| 57 | + patterns.append(path(url, view_fn, name=urlname)) |
58 | 58 | return patterns
|
59 | 59 |
|
60 | 60 |
|
|
0 commit comments