-
Notifications
You must be signed in to change notification settings - Fork 23
recover excercise new pull req #109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
6a23a15
36e46df
b09ddfd
d84a6a2
787d661
89ad530
fd41248
8419473
dddd67d
e01e794
559ac72
3338c71
27c96b7
a168072
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,7 @@ import ( | |
| "io/fs" | ||
| "os" | ||
| "path/filepath" | ||
| "strings" | ||
| "sync" | ||
|
|
||
| "gopkg.in/yaml.v3" | ||
|
|
@@ -124,6 +125,19 @@ func Get(slug string) (Exercise, error) { | |
| return ex, nil | ||
| } | ||
| } | ||
| // Fallback: if an embedded template or solution exists, synthesize an Exercise entry | ||
| if templateExists(slug) || SolutionExists(slug) { | ||
| fmt.Fprintf(os.Stderr, | ||
| "Warning: exercise '%s' found in templates/solutions but missing from catalog.yaml\n", | ||
| slug, | ||
| ) | ||
| return Exercise{ | ||
| Slug: slug, | ||
| Title: formatSlugAsTitle(slug), // e.g., "110 Recover" | ||
| TestRegex: ".*", | ||
| Hints: []string{"This exercise is missing proper catalog metadata. Check documentation."}, | ||
| }, nil | ||
|
Comment on lines
+128
to
+139
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Omesh2004 : Why do we need support this?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The formatSlugAsTitle helper is only used in the fallback path when the slug isn’t in catalog.yaml (and not in local ./exercises) but exists in embedded templates/solutions..
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a nice edition, could you add this as separate PR? |
||
| } | ||
| return Exercise{}, fmt.Errorf("exercise not found: %s", slug) | ||
| } | ||
|
|
||
|
|
@@ -187,4 +201,37 @@ func copyExerciseTemplate(slug string) error { | |
| }) | ||
| } | ||
|
|
||
| func formatSlugAsTitle(slug string) string { | ||
| s := strings.TrimSpace(slug) | ||
| if s == "" { | ||
| return "Exercise" | ||
| } | ||
| parts := strings.Split(s, "_") | ||
| for i, p := range parts { | ||
| if p == "" { | ||
| continue | ||
| } | ||
| // Keep purely numeric segments as-is (e.g., "110") | ||
| isDigits := true | ||
| for _, r := range p { | ||
| if r < '0' || r > '9' { | ||
| isDigits = false | ||
| break | ||
| } | ||
| } | ||
| if isDigits { | ||
| parts[i] = p | ||
| continue | ||
| } | ||
| upper := strings.ToUpper(p) | ||
| switch upper { | ||
| case "JSON", "XML", "HTTP", "CLI", "KV", "ID", "URL", "IO": | ||
| parts[i] = upper | ||
| default: | ||
| parts[i] = strings.ToUpper(p[:1]) + strings.ToLower(p[1:]) | ||
| } | ||
| } | ||
| return strings.Join(parts, " ") | ||
| } | ||
|
Comment on lines
+204
to
+235
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you elaborate what are we trying to achieve here?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. basically this helper function is alloting titles based on the slugs in case the same arent present in catalog.yaml file 110_recover -> 110 Recover |
||
|
|
||
| var ErrNoTemplates = errors.New("no templates found") | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| package recover_exercise | ||
|
|
||
| // DoWork simulates a function that might panic if the input is negative. | ||
| // | ||
| // It is designed to be called by Run, which should demonstrate | ||
| // how to safely handle the panic using recover(). | ||
| func DoWork(n int) { | ||
| if n < 0 { | ||
| // A panic occurs if n is negative | ||
| panic("input cannot be negative") | ||
| } | ||
| // Normal, non-panicking code path... | ||
| } | ||
|
|
||
| // Run calls DoWork and uses defer/recover to safely handle any panic. | ||
| // It returns the recovered panic value or nil if no panic occurred. | ||
| func Run(n int) (recoveredValue interface{}) { | ||
| // The deferred function is executed just before Run returns. | ||
| defer func() { | ||
| // Call recover() to check if a panic has occurred. | ||
| if r := recover(); r != nil { | ||
| // If recover() returns a non-nil value (a panic occurred), | ||
| // assign it to the named return variable 'recoveredValue'. | ||
| recoveredValue = r | ||
| } | ||
| }() | ||
|
|
||
| DoWork(n) | ||
|
|
||
| // 'recoveredValue' is returned. It will be the panic value if | ||
| // a panic occurred and was recovered, or nil otherwise. | ||
| return recoveredValue | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| package recover_exercise | ||
|
|
||
| // DoWork simulates a function that might panic if the input is negative. | ||
| func DoWork(n int) { | ||
| if n < 0 { | ||
| // A panic occurs if n is negative | ||
| panic("input cannot be negative") | ||
| } | ||
| // Normal, non-panicking code path... | ||
| } | ||
|
|
||
| // Run should call DoWork and safely recover from any panic | ||
| // that occurs during its execution, returning the recovered value. | ||
| // It should return nil if no panic occurred. | ||
| func Run(n int) (recoveredValue interface{}) { | ||
| // 1. Add your 'defer' statement here. | ||
| // 2. The deferred function should call recover() and assign the result | ||
| // to 'recoveredValue' if it is not nil. | ||
|
|
||
| // Your code here: | ||
|
|
||
| DoWork(n) | ||
|
|
||
| return recoveredValue | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| package recover_exercise | ||
|
|
||
| import ( | ||
| "testing" | ||
| ) | ||
|
|
||
| func TestRun_NoPanic(t *testing.T) { | ||
| t.Parallel() | ||
| result := Run(10) | ||
| if result != nil { | ||
| t.Errorf("Run(10) should not panic and should return nil. Got: %v", result) | ||
| } | ||
| } | ||
|
|
||
| func TestRun_WithPanic(t *testing.T) { | ||
| t.Parallel() | ||
| expectedPanicValue := "input cannot be negative" | ||
| result := Run(-5) | ||
|
|
||
| if result == nil { | ||
| t.Errorf("Run(-5) should panic and recover, returning the panic value. Got nil") | ||
| } | ||
|
|
||
| // Check if the recovered value is what we expected | ||
| if resultAsString, ok := result.(string); !ok || resultAsString != expectedPanicValue { | ||
| t.Errorf("Run(-5) recovered with unexpected value. Expected: %q, Got: %v (%T)", expectedPanicValue, result, result) | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Restore string hints to keep catalog schema valid
Every existing catalog entry provides
hintsas plain strings. The loader expects a[]string; supplying maps (hint_type,text) will fail to unmarshal and break catalog loading. Please keep hints as simple strings (or extend the loader before changing the schema).📝 Committable suggestion
🤖 Prompt for AI Agents