Skip to content

Quick Start ​

Get up and running with Python Requirements Parser in minutes.

Installation ​

Add the package to your Go project:

bash
go get github.com/scagogogo/python-requirements-parser

Basic Usage ​

Parse requirements.txt ​

go
package main

import (
    "fmt"
    "log"
    
    "github.com/scagogogo/python-requirements-parser/pkg/parser"
)

func main() {
    // Create a parser
    p := parser.New()
    
    // Parse from file
    reqs, err := p.ParseFile("requirements.txt")
    if err != nil {
        log.Fatal(err)
    }
    
    // Print all packages
    for _, req := range reqs {
        if !req.IsComment && !req.IsEmpty && req.Name != "" {
            fmt.Printf("Package: %s, Version: %s\n", req.Name, req.Version)
        }
    }
}

Parse from string ​

go
content := `
flask==2.0.1
django>=3.2.0,<4.0.0
requests>=2.25.0  # HTTP library
# Development dependencies
pytest>=6.0.0
`

p := parser.New()
reqs, err := p.ParseString(content)
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Found %d requirements\n", len(reqs))

Edit requirements.txt ​

Use the PositionAwareEditor for minimal diff editing:

go
package main

import (
    "fmt"
    "log"
    
    "github.com/scagogogo/python-requirements-parser/pkg/editor"
)

func main() {
    // Create position-aware editor
    editor := editor.NewPositionAwareEditor()
    
    // Parse requirements file
    content := `flask==1.0.0  # Web framework
django>=3.2.0  # Another framework
requests>=2.25.0  # HTTP library`
    
    doc, err := editor.ParseRequirementsFile(content)
    if err != nil {
        log.Fatal(err)
    }
    
    // Update single package
    err = editor.UpdatePackageVersion(doc, "flask", "==2.0.1")
    if err != nil {
        log.Fatal(err)
    }
    
    // Batch update multiple packages
    updates := map[string]string{
        "django":  ">=3.2.13",
        "requests": ">=2.28.0",
    }
    
    err = editor.BatchUpdateVersions(doc, updates)
    if err != nil {
        log.Fatal(err)
    }
    
    // Serialize with minimal changes
    result := editor.SerializeToString(doc)
    fmt.Println("Updated requirements.txt:")
    fmt.Println(result)
}

Parser Options ​

Recursive file resolution ​

Parse files that reference other requirements files:

go
// Enable recursive parsing
p := parser.NewWithRecursiveResolve()
reqs, err := p.ParseFile("requirements.txt")

// This will also parse files referenced with -r or --requirement

Environment variable processing ​

go
// Create parser with environment variable processing
p := parser.New()
p.ProcessEnvVars = true

// Now ${VAR} in requirements will be replaced with environment values
reqs, err := p.ParseString("package==${VERSION}")

Editor Comparison ​

Choose the right editor for your needs:

EditorUse CaseDiff SizePerformance
PositionAwareEditor ⭐Minimal diff editingSmallestFastest updates
VersionEditorV2Full reconstructionMediumFast parsing
VersionEditorSimple text editingLargestBasic

Best for production environments where you need minimal changes:

go
editor := editor.NewPositionAwareEditor()
doc, err := editor.ParseRequirementsFile(content)

// Only changes the specific version constraints
err = editor.UpdatePackageVersion(doc, "flask", "==2.0.1")
result := editor.SerializeToString(doc)

VersionEditorV2 ​

Good for comprehensive editing with full parser support:

go
editor := editor.NewVersionEditorV2()
doc, err := editor.ParseRequirementsFile(content)

// Full editing capabilities
err = editor.AddPackage(doc, "fastapi", ">=0.95.0", []string{"all"}, `python_version >= "3.7"`)
err = editor.UpdatePackageExtras(doc, "django", []string{"rest", "auth"})
result := editor.SerializeToString(doc)

Common Patterns ​

Security updates ​

go
editor := editor.NewPositionAwareEditor()
doc, err := editor.ParseRequirementsFile(content)

securityUpdates := map[string]string{
    "django":         ">=3.2.13,<4.0.0",  // Security patch
    "requests":       ">=2.28.0",          // Security patch
    "cryptography":   ">=39.0.2",          // Security patch
}

err = editor.BatchUpdateVersions(doc, securityUpdates)
result := editor.SerializeToString(doc)

Version pinning ​

go
packages := editor.ListPackages(doc)
for _, pkg := range packages {
    if strings.HasPrefix(pkg.Version, ">=") {
        // Pin to exact version
        version := extractLatestVersion(pkg.Version)
        err := editor.UpdatePackageVersion(doc, pkg.Name, "=="+version)
        if err != nil {
            log.Printf("Failed to pin %s: %v", pkg.Name, err)
        }
    }
}

Package information ​

go
// Get specific package info
info, err := editor.GetPackageInfo(doc, "flask")
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Package: %s\n", info.Name)
fmt.Printf("Version: %s\n", info.Version)
fmt.Printf("Extras: %v\n", info.Extras)
fmt.Printf("Markers: %s\n", info.Markers)
fmt.Printf("Comment: %s\n", info.Comment)

// List all packages
packages := editor.ListPackages(doc)
fmt.Printf("Total packages: %d\n", len(packages))

Error Handling ​

go
// Parse with error handling
reqs, err := p.ParseFile("requirements.txt")
if err != nil {
    log.Fatalf("Failed to parse requirements: %v", err)
}

// Update with error handling
err = editor.UpdatePackageVersion(doc, "nonexistent", "==1.0.0")
if err != nil {
    log.Printf("Package not found: %v", err)
}

// Batch update with partial failure handling
err = editor.BatchUpdateVersions(doc, updates)
if err != nil {
    log.Printf("Some updates failed: %v", err)
    // Continue with successful updates
}

Next Steps ​

Performance Tips ​

  1. Use PositionAwareEditor for minimal diff editing
  2. Batch updates instead of individual updates
  3. Reuse parser instances for multiple files
  4. Enable recursive parsing only when needed
go
// Efficient batch processing
editor := editor.NewPositionAwareEditor()

// Process multiple files
for _, file := range files {
    doc, err := editor.ParseRequirementsFile(file.Content)
    if err != nil {
        continue
    }
    
    // Batch update all packages at once
    err = editor.BatchUpdateVersions(doc, updates)
    if err != nil {
        log.Printf("Failed to update %s: %v", file.Name, err)
        continue
    }
    
    file.UpdatedContent = editor.SerializeToString(doc)
}

Released under the MIT License