script

package module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 17, 2025 License: MIT Imports: 10 Imported by: 0

README

package script

This package is intended as a collection of helper functions and tools fow quick construction of scripts that process .csv tables.

Note that this is a work in progress. API is not guaranteed to be stable.

Example usage

This demonstrates a very basic case: reading from stdin, checking whether array len is 2 and switching array elements.

package main

import (
	"context"
	"errors"
	"fmt"
	"os/signal"
	"syscall"

	"code.uint32.ru/dmitry/script"
)

func main() {
	ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGTERM, syscall.SIGINT)
	defer stop()

	reader := script.NewStdinReader()
	writer := script.NewStdoutWriter()

	processor := func(_ context.Context, in []string) ([]string, error) {
		if len(in) != 2 {
			return nil, errors.New("incorrect input len")
		}

		return []string{in[1], in[0]}, nil
	}

	conf := script.RunConfig{
		Input:     reader,
		Output:    writer,
		Processor: processor,
	}

	if _, err := script.Run(ctx, conf); err != nil {
		fmt.Println(err)
	}
}

A more conplicated example featuring a processor which is itself a struct with external dependency.

package main

import (
	"context"
	"fmt"
	"os/signal"
	"syscall"

	"code.uint32.ru/dmitry/script"
)

// ExternalDep represent an external dependency
// which your script utilizes. This can be a DB connection etc.
type ExternalDep interface {
	QueryID(string) ([]string, error)
}

type Processor struct {
	dep ExternalDep
}

func New(e ExternalDep) *Processor {

	return &Processor{
		dep: e,
	}
}

func (p *Processor) Process(ctx context.Context, in []string) ([]string, error) {
	var out []string

	result, err := p.dep.QueryID(in[0])
	if err != nil {
		// you can as well record the error and continue
		// processing without yielding the error here
		return nil, err
	}

	out = append(out, result...)
	out = append(out, "processed")

	return out, nil
}

func main() {
	ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGTERM, syscall.SIGINT)
	defer stop()

	r, err := script.NewCSVReader("/tmp/some_file.csv")
	if err != nil {
		panic(err)
	}

	defer func() {
		if err := r.Close(); err != nil {
			fmt.Println("err closing reader", err)
		}
	}()

	w, err := script.NewCSVWriter("/tmp/some_output.csv")
	if err != nil {
		panic(err)
	}

	defer func() {
		if err := w.Close(); err != nil {
			fmt.Println("err closing writer", err)
		}
	}()

    // intializing the processor
	p := New(ExternalDep(nil))

	conf := script.RunConfig{
		Input:     r,
		Output:    w,
		Processor: p.Process, // Process implements script.Processor
	}

	if _, err := script.Run(ctx, conf); err != nil {
		fmt.Println(err)
	}
}

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	EOF             error = io.EOF
	ErrNoProcessors       = errors.New("script: no processors provided")
)

Functions

This section is empty.

Types

type CSVReader

type CSVReader struct {
	// contains filtered or unexported fields
}

func NewCSVReader

func NewCSVReader(filename string) (*CSVReader, error)

CSV creates csv.Reader reading from filename.

func (*CSVReader) Close

func (c *CSVReader) Close() error

func (*CSVReader) Read

func (c *CSVReader) Read() ([]string, error)

type CSVWriter

type CSVWriter struct {
	// contains filtered or unexported fields
}

func NewCSVWriter

func NewCSVWriter(filename string) (*CSVWriter, error)

CSV creates csv.Writer writing to underlying file. Do not forget to call Close method once you are done.

func (*CSVWriter) Close

func (c *CSVWriter) Close() error

Close flushes underlying csv.Writer and closes file.

func (*CSVWriter) Error

func (c *CSVWriter) Error() error

Error return last encountered error.

func (*CSVWriter) Write

func (c *CSVWriter) Write(record []string) error

Write writer row to csv. Writes are buffered

type MemReader

type MemReader struct {
	// contains filtered or unexported fields
}

func NewMemReader

func NewMemReader(records [][]string) *MemReader

func (*MemReader) Read

func (m *MemReader) Read() ([]string, error)

type MemWriter

type MemWriter struct {
	// contains filtered or unexported fields
}

func NewMemWriter

func NewMemWriter() *MemWriter

func (*MemWriter) Output

func (m *MemWriter) Output() [][]string

func (*MemWriter) Write

func (m *MemWriter) Write(record []string) error

type NopWriter

type NopWriter struct{}

func NewNopWriter

func NewNopWriter() *NopWriter

func (*NopWriter) Write

func (d *NopWriter) Write([]string) error

type Processor

type Processor func(context.Context, []string) ([]string, error)

Processor accepts string slice, does what it should and returns output. Non-nil error returned by Processor stops further processing.

func ChainProcessor added in v0.3.0

func ChainProcessor(processors ...Processor) Processor

Chain chains provided Processors. When an error is returned by a Processor in chain, processing stops and the error is retuned without running further stages.

type Reader

type Reader interface {
	// Read is called by Processor to obtain input
	// for processing. Read must return EOF/io.EOF to indicate
	// that there is no more input.
	Read() ([]string, error)
}

type RunConfig

type RunConfig struct {
	Input       Reader
	Output      Writer
	Processor   Processor
	Offset      int
	Limit       int
	Concurrency int
}

type RunResult added in v0.2.0

type RunResult struct {
	Read      int // number of records read without error (offset count not included)
	Processed int // number of records processed without error
	Written   int // number of records written to Writer without error
}

func Run

func Run(ctx context.Context, r RunConfig) (RunResult, error)

Run starts the script described by r. First Read is called offset times with output of Read being discarded. Then limit Reads are made and processor is called for each portion of data. If limit is 0 then Run keeps processing input until it receives EOF from Reader. Run fails on any error including Reader error, Writer error and Processor error. The returned RunResult is AWAYS VALID and indicates the actual progress of script. Returned error explains why Run failed. It may be either read, process or write error.

type StdinReader

type StdinReader struct {
	// contains filtered or unexported fields
}

StdinReader reads from stdin

func NewStdinReader

func NewStdinReader() *StdinReader

func (*StdinReader) Read

func (s *StdinReader) Read() ([]string, error)

Read reads from stdin until \n character then splits result at "," separator and returns the resulting slice. It returns EOF when nothing left to read.

type StdoutWriter

type StdoutWriter struct{}

func NewStdoutWriter

func NewStdoutWriter() *StdoutWriter

func (*StdoutWriter) Write

func (s *StdoutWriter) Write(in []string) error

type Writer

type Writer interface {
	// Write is called by Processor to record
	// output.
	Write([]string) error
}

func ChainWriter added in v0.3.0

func ChainWriter(writers ...Writer) Writer

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL