Skip to content
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

devit #84

Merged
merged 1 commit into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions slices.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
type BaseModel struct{}

var (
baseModelType = reflect.TypeOf((*BaseModel)(nil)).Elem()

Check failure on line 18 in slices.go

View workflow job for this annotation

GitHub Actions / lint

var `baseModelType` is unused (unused)
)

// New parses a goquery doc into a slice of structs.
Expand Down Expand Up @@ -63,45 +63,45 @@
// fmt.Printf("pp %+v\n", pp)
// }
// }
func New[T any](doc *goquery.Document) ([]T, error) {
dType := reflect.TypeOf((*T)(nil)).Elem()
if dType.Kind() != reflect.Struct && dType.Kind() != reflect.Ptr {
return nil, fmt.Errorf("expected struct, got %s", dType.Kind())
}
results := make([]T, 0)
var cfg *SelectorConfig
for i := 0; i < dType.NumField(); i++ {
cfg = NewSelectorConfig(dType.Field(i).Tag)

Check warning on line 74 in slices.go

View check run for this annotation

Codeac.io / Codeac Code Quality

CodeDuplication

This block of 8 lines is too similar to slices.go:628
if cfg.DataSelector == "" {
return nil, ErrSelectorNotFound{
Typ: dType,

Check warning on line 77 in slices.go

View check run for this annotation

Codeac.io / Codeac Code Quality

CodeDuplication

This block of 8 lines is too similar to slices.go:364
Field: dType.Field(i),
Cfg: cfg,
}
}
dataRows := doc.Find(cfg.DataSelector)
if dataRows.Length() <= 0 {
continue
}
if cfg.HeadSelector != "" && cfg.HeadSelector != "-" {
_ = dataRows.RemoveFiltered(cfg.HeadSelector)
}
if len(results) < dataRows.Length() {
results = make([]T, dataRows.Length())
}
for j := 0; j < dataRows.Length(); j++ {
err := SetStructField(
&results[j],
dType.Field(i), // name of the field to set
dataRows.Eq(j), // goquery selection for cell
&selector{
control: cfg.ControlTag,
query: cfg.QuerySelector,
}, // selector for the inner cell
)
if err != nil {
return nil, fmt.Errorf(
"failed to set field %s: %s",

Check warning on line 104 in slices.go

View check run for this annotation

Codeac.io / Codeac Code Quality

CodeDuplication

This block of 28 lines is too similar to slices.go:371

Check warning on line 104 in slices.go

View check run for this annotation

Codeac.io / Codeac Code Quality

CodeDuplication

This block of 19 lines is too similar to slices.go:649
dType.Field(i).Name,
err,
)
Expand Down Expand Up @@ -358,45 +358,45 @@
// The struct given as an argument must have a field with the
// tag seltabl, a header selector with the tag hSel, and a data
// selector with the tag key dSel.
func NewCh[T any](doc *goquery.Document, ch chan T) error {
dType := reflect.TypeOf((*T)(nil)).Elem()
if dType.Kind() != reflect.Struct && dType.Kind() != reflect.Ptr {
return fmt.Errorf("expected struct, got %s", dType.Kind())
}
results := make([]T, 0)
var cfg *SelectorConfig
for i := 0; i < dType.NumField(); i++ {
cfg = NewSelectorConfig(dType.Field(i).Tag)
if cfg.DataSelector == "" {
return ErrSelectorNotFound{
Typ: dType,

Check warning on line 372 in slices.go

View check run for this annotation

Codeac.io / Codeac Code Quality

CodeDuplication

This block of 8 lines is too similar to slices.go:69

Check warning on line 372 in slices.go

View check run for this annotation

Codeac.io / Codeac Code Quality

CodeDuplication

This block of 11 lines is too similar to slices.go:520
Field: dType.Field(i),
Cfg: cfg,
}
}
dataRows := doc.Find(cfg.DataSelector)
if dataRows.Length() <= 0 {
continue
}
if cfg.HeadSelector != "" && cfg.HeadSelector != "-" {
_ = dataRows.RemoveFiltered(cfg.HeadSelector)
}
if len(results) < dataRows.Length() {
results = make([]T, dataRows.Length())
}
for j := 0; j < dataRows.Length(); j++ {
err := SetStructField(
&results[j],
dType.Field(i), // name of the field to set
dataRows.Eq(j), // goquery selection for cell
&selector{
control: cfg.ControlTag,
query: cfg.QuerySelector,
}, // selector for the inner cell
)
if err != nil {
return fmt.Errorf(
"failed to set field %s: %s",

Check warning on line 399 in slices.go

View check run for this annotation

Codeac.io / Codeac Code Quality

CodeDuplication

This block of 28 lines is too similar to slices.go:76
dType.Field(i).Name,
err,
)
Expand Down Expand Up @@ -517,18 +517,18 @@
doc *goquery.Document,
ch chan T,
fn F,
) error {
dType := reflect.TypeOf((*T)(nil)).Elem()
if dType.Kind() != reflect.Struct && dType.Kind() != reflect.Ptr {
return fmt.Errorf("expected struct, got %s", dType.Kind())
}
results := make([]T, 0)
var cfg *SelectorConfig
for i := 0; i < dType.NumField(); i++ {
cfg = NewSelectorConfig(dType.Field(i).Tag)
if cfg.DataSelector == "" {
continue
}

Check warning on line 531 in slices.go

View check run for this annotation

Codeac.io / Codeac Code Quality

CodeDuplication

This block of 11 lines is too similar to slices.go:361
dataRows := doc.Find(cfg.DataSelector)
if dataRows.Length() <= 0 {
return ErrNoDataFound{
Expand All @@ -536,32 +536,32 @@
Field: dType.Field(i),
Cfg: cfg,
}
}
if cfg.HeadSelector != "" && cfg.HeadSelector != "-" {
_ = dataRows.RemoveFiltered(cfg.HeadSelector)
}
if len(results) < dataRows.Length() {
results = make([]T, dataRows.Length())
}
for j := 0; j < dataRows.Length(); j++ {
err := SetStructField(
&results[j],
dType.Field(i), // name of the field to set
dataRows.Eq(j), // goquery selection for cell
&selector{
control: cfg.ControlTag,
query: cfg.QuerySelector,
}, // selector for the inner cell
)
if err != nil {
return fmt.Errorf(
"failed to set field %s: %s",
dType.Field(i).Name,
err,
)
}
if fn(results[j]) {
ch <- results[j]

Check warning on line 564 in slices.go

View check run for this annotation

Codeac.io / Codeac Code Quality

CodeDuplication

This block of 25 lines is too similar to slices.go:85
}
}
}
Expand Down Expand Up @@ -623,3 +623,86 @@
}
return NewChFn(doc, ch, fn)
}

// NewPl parses a reader into a slice of structs with parallel processing.
func NewPl[T any](doc *goquery.Document) ([]T, error) {
dType := reflect.TypeOf((*T)(nil)).Elem()
if dType.Kind() != reflect.Struct && dType.Kind() != reflect.Ptr {
return nil, fmt.Errorf("expected struct, got %s", dType.Kind())
}
results := make([]T, 0)
var cfg *SelectorConfig
errCh := make(chan error)
for i := 0; i < dType.NumField(); i++ {

Check warning on line 636 in slices.go

View check run for this annotation

Codeac.io / Codeac Code Quality

CodeDuplication

This block of 8 lines is too similar to slices.go:66
go func(i int) {
cfg = NewSelectorConfig(dType.Field(i).Tag)
if cfg.DataSelector == "" {
errCh <- ErrSelectorNotFound{
Typ: dType,
Field: dType.Field(i),
Cfg: cfg,
}
}
dataRows := doc.Find(cfg.DataSelector)
if dataRows.Length() <= 0 {
return
}
if cfg.HeadSelector != "" && cfg.HeadSelector != "-" {
_ = dataRows.RemoveFiltered(cfg.HeadSelector)
}
if len(results) < dataRows.Length() {
results = make([]T, dataRows.Length())
}
for j := 0; j < dataRows.Length(); j++ {
err := SetStructField(
&results[j],
dType.Field(i), // name of the field to set
dataRows.Eq(j), // goquery selection for cell
&selector{
control: cfg.ControlTag,
query: cfg.QuerySelector,
}, // selector for the inner cell
)
if err != nil {
errCh <- fmt.Errorf(
"failed to set field %s: %s",

Check warning on line 668 in slices.go

View check run for this annotation

Codeac.io / Codeac Code Quality

CodeDuplication

This block of 19 lines is too similar to slices.go:85
dType.Field(i).Name,
err,
)
}
}
}(i)
}
if len(results) < 1 {
return nil, fmt.Errorf("no data found")
}
return results, nil
}

// NewFromReaderPl parses a reader into a slice of structs with parallel processing.
func NewFromReaderPl[T any](r io.Reader) ([]T, error) {
doc, err := goquery.NewDocumentFromReader(r)
if err != nil {
return nil, fmt.Errorf("failed to parse html: %w", err)
}
return NewPl[T](doc)
}

// NewFromStringPl parses a string into a slice of structs with parallel processing.
func NewFromStringPl[T any](htmlInput string) ([]T, error) {
reader := strings.NewReader(htmlInput)
doc, err := goquery.NewDocumentFromReader(reader)
if err != nil {
return nil, fmt.Errorf("failed to parse html: %w", err)
}
return NewPl[T](doc)
}

// NewFromBytesPl parses a byte slice into a slice of structs with parallel processing.
func NewFromBytesPl[T any](b []byte) ([]T, error) {
doc, err := goquery.NewDocumentFromReader(bytes.NewReader(b))
if err != nil {
return nil, fmt.Errorf("failed to parse html: %w", err)
}
return NewPl[T](doc)
}
1 change: 0 additions & 1 deletion tools/seltabls/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,3 @@ Manually, one can run the tests with:
```sh
go test ./...
```

Loading