| 78 | | error: invalid feature 'non-existent' |
| 79 | | - when computing build properties for target 'foo' |
| 80 | | - when build project in '.' |
| 81 | | |
| 82 | | To implement this we need: |
| 83 | | |
| 84 | | - Maintain those user-contexts |
| 85 | | - Arrange for user-context to be printed or recorded when |
| 86 | | error happens |
| 87 | | - Do something about 'stray' exceptions through in |
| 88 | | Python code, like caused by bugs |
| 89 | | |
| 90 | | 2. We should have a module errors with two functions: |
| 91 | | 'push-context' and 'pop-context'. The first takes a |
| 92 | | string description of what we're doing now. Every function |
| 93 | | that does something interesting from the user's point of |
| 94 | | view should be written like: |
| 95 | | |
| 96 | | try: |
| 97 | | errors.push_context("Doing something") |
| 98 | | # do something |
| 99 | | finally: |
| 100 | | errors.pop_context() |
| 101 | | |
| 102 | | The try/finally is needed so that if stray exception is thrown, |
| 103 | | the pushed used context does not stay pushed forever. |
| 104 | | |
| 105 | | 3. Whenever we run into error condition that can be explained in |
| 106 | | user terms, we'll use errors.error(). That function will |
| 107 | | create new exception type, record current user context into |
| 108 | | it, and raise that exception. |
| 109 | | |
| 110 | | 4. Python exception should never be allowed to escape back to jam. |
| 111 | | Every function called from bjam should try/catch and print |
| 112 | | the exception. |
| 113 | | |
| 114 | | 5. Every function called from bjam will get bjam stack trace |
| 115 | | and add it to user context. So, if error happens user will |
| 116 | | see what line from Jamfile caused it. |
| 117 | | |
| 118 | | 6. It's possible that we either detect error at too low |
| 119 | | level to provide any explanation, or the error is detected |
| 120 | | by Python interpreter. In which case, an ordinary exception |
| 121 | | will be thrown. To still provide some context, we should |
| 122 | | use try/catch at various strategic places, catch such stray |
| 123 | | exceptions, and throw new exception, that holds current user |
| 124 | | context and the original exception. So, if we try to say |
| 125 | | interate over None somewhere deep, we'll get an error message |
| 126 | | like this: |
| 127 | | |
| 128 | | internal-error: Itetarion over non-sequence |
| 129 | | - when building target 'foo' |
| 130 | | |
| 131 | | Use --backtrace to see Python backtrace |
| 132 | | |
| 133 | | Note that this output is not very useful to debug anything. |
| 134 | | It's primarily meant to avoid completely freaking out users |
| 135 | | who are not accustomed to Python stacktraces. This way, they'll |
| 136 | | at least have the time to open Python docs before getting |
| 137 | | real Python stracktrace. |
| 138 | | |
| 139 | | 7. When printing real stacktrace, we can be inside Python code |
| 140 | | called from Jam code, called from Python code etc. Technically, |
| | 81 | If a {{{--stacktrace}}} parameter is specified on the command line, we'll print raw Python backtrace. |
| | 82 | Such a backtrace can include Python code called from Jam code, called from Python code etc. Technically, |