Skip to main content

lom — packaged as a Python wheel

Project description

lom

A command-line tool for Neo4j with an interactive shell that can be used by people and by AI agents. Connect to a Neo4j database and the Neo4j Aura management API from a single binary — run Cypher queries, manage cloud instances, and perform administrative operations.


Contents


Getting started

Prerequisites

  • Go 1.24 or later

Build

git clone <repo-url>
cd go-cli-tool
go build -o bin/lom ./cmd/lom

Run

# Run a subcommand directly
./bin/lom cypher "MATCH (n:Person) RETURN n.name LIMIT 5"
./bin/lom cloud instances list
./bin/lom admin show-databases
./bin/lom config list

# Point at a specific config file
./bin/lom --config-file ~/.lom/config.json cloud instances list

# Control output format
./bin/lom cypher --format json "MATCH (n) RETURN n LIMIT 10"
./bin/lom cloud instances list --format json
./bin/lom cloud instances list --format toon

Commands

All functionality is exposed as top-level subcommands. Running lom with no arguments prints help.

Subcommand Description
cypher [query] Execute a Cypher query against the connected database
cloud Manage Neo4j Aura cloud resources
admin Administrative operations against the connected database
config Manage CLI configuration

cypher

Executes a Cypher query against the connected database.

lom cypher "MATCH (n) RETURN n LIMIT 5"
lom cypher --param name=Alice "MATCH (n:Person {name:\$name}) RETURN n"
lom cypher --format json "MATCH (n) RETURN n"
lom cypher --format toon "MATCH (n)-[r]->(m) RETURN n,r,m"
lom cypher --limit 100 "MATCH (n) RETURN n"

Flags (placed before the query):

Flag Description
--param key=value Add a query parameter (repeatable). Values are auto-typed: int, float, bool, string.
--format table|toon|json|pretty-json|graph Override the output format for this query.
--limit N Override the auto-injected row limit.

Requires a Neo4j connection. If credentials are not configured, you are prompted to enter them on first use and they are saved to the config file.

cloud

Manages Neo4j Aura cloud resources.

Requires Aura credentials. If aura.client_id or aura.client_secret are not configured, you are prompted to enter them on first use.

lom cloud instances list
lom cloud instances ls                                                  # alias
lom cloud instances get <id>
lom cloud instances create name=<n> tenant=<id> [cloud=<p>] [region=<r>] [type=<t>] [version=<v>] [memory=<size>]
lom cloud instances update <id> [name=<new-name>] [memory=<size>]
lom cloud instances pause <id>
lom cloud instances resume <id>
lom cloud instances delete <id>
lom cloud instances rm <id>                                             # alias

lom cloud projects list
lom cloud projects get <id>

instances create requires name and tenant. All other fields fall back to aura.instance_defaults in the config. Set defaults to avoid repeating them on every invocation:

lom config set aura.instance_defaults.tenant_id abc-123
lom config set aura.instance_defaults.cloud_provider aws
lom cloud instances create name=my-db

Save your password. When instances create succeeds, the initial password is shown exactly once and cannot be recovered.

admin

Runs administrative commands against the connected database.

Requires a Neo4j connection. Same prerequisite as cypher.

lom admin show-users
lom admin show-databases

config

Manages CLI configuration. Changes made with set, delete, and reset are persisted to the config file immediately and take effect in the current session.

lom config list                                # show all keys, values, and descriptions
lom config list --format json
lom config set neo4j.uri bolt://myhost:7687
lom config set cypher.output_format json
lom config set aura.instance_defaults.region us-east-1
lom config delete neo4j.password              # reset a key to its default (prompts)
lom config reset                              # wipe config file, restore all defaults (prompts)

Configuration

Settings are resolved in this order, highest priority first:

CLI flags  >  environment variables  >  config file  >  defaults

Config file

The default config file path is ~/.lom/config.json. The directory and file are created automatically when credentials are first saved via an interactive prompt. Pass --config-file <path> to use a different location.

A full example:

{
  "log_level": "info",
  "log_format": "text",
  "log_output": "stderr",
  "log_file": "",
  "neo4j": {
    "uri": "bolt://localhost:7687",
    "username": "neo4j",
    "password": "secret",
    "database": "neo4j"
  },
  "aura": {
    "client_id": "your-client-id",
    "client_secret": "your-client-secret",
    "timeout_seconds": 30,
    "instance_defaults": {
      "tenant_id": "your-tenant-id",
      "cloud_provider": "gcp",
      "region": "europe-west1",
      "type": "enterprise-db",
      "version": "5",
      "memory": "8GB"
    }
  },
  "cypher": {
    "shell_limit": 25,
    "exec_limit": 100,
    "output_format": "table"
  },
  "telemetry": {
    "metrics": true
  }
}

Environment variables

All variables use the LOM_ prefix. Nested keys use underscores.

Variable Default Description
LOM_LOG_LEVEL info Log level: debug, info, warn, error
LOM_LOG_FORMAT text Log format: text, json
LOM_LOG_OUTPUT stderr Log destination: stderr, stdout, file
LOM_LOG_FILE (empty) Log file path (used when LOM_LOG_OUTPUT=file)
LOM_NEO4J_URI bolt://localhost:7687 Neo4j bolt URI
LOM_NEO4J_USERNAME neo4j Neo4j username
LOM_NEO4J_PASSWORD (empty) Neo4j password — prefer env over config file
LOM_NEO4J_DATABASE neo4j Neo4j database name
LOM_AURA_CLIENT_ID (empty) Aura API client ID
LOM_AURA_CLIENT_SECRET (empty) Aura API client secret — prefer env over config file
LOM_AURA_TIMEOUT_SECONDS 30 Aura API request timeout
LOM_AURA_INSTANCE_DEFAULTS_TENANT_ID (empty) Default tenant ID for new instances
LOM_AURA_INSTANCE_DEFAULTS_CLOUD_PROVIDER gcp Default cloud provider: aws, gcp, azure
LOM_AURA_INSTANCE_DEFAULTS_REGION europe-west1 Default region for new instances
LOM_AURA_INSTANCE_DEFAULTS_TYPE enterprise-db Default instance type
LOM_AURA_INSTANCE_DEFAULTS_VERSION 5 Default Neo4j version
LOM_AURA_INSTANCE_DEFAULTS_MEMORY 8GB Default instance memory
LOM_CYPHER_SHELL_LIMIT 25 Default LIMIT injected into cypher queries
LOM_CYPHER_EXEC_LIMIT 100 Default LIMIT in non-interactive mode
LOM_CYPHER_OUTPUT_FORMAT table Default output format: table, json, pretty-json, graph, toon
LOM_TELEMETRY_METRICS true Send anonymous usage metrics to Neo4j

Security note: LOM_NEO4J_PASSWORD and LOM_AURA_CLIENT_SECRET are intentionally not available as CLI flags. Passing secrets as flags exposes them in shell history and ps output.

CLI flags

--config-file string      Path to a JSON configuration file
--neo4j-uri string        Neo4j bolt URI
--neo4j-username string   Neo4j username
--neo4j-database string   Neo4j database name
--aura-client-id string   Aura API client ID
--aura-timeout int        Aura API timeout in seconds
--log-level string        Log level: debug, info, warn, error
--log-format string       Log format: text, json
--log-output string       Log destination: stderr, stdout, file
--log-file string         Log file path (when --log-output=file)
--format string           Output format: table, json, pretty-json, graph
--no-metrics              Disable anonymous usage metrics

--agent                   Enable agent mode (see Agent mode section)
--rw                      Permit write/mutating operations in agent mode
--request-id string       Correlation ID for agent-mode JSON responses
--timeout duration        Maximum command execution time (e.g. 30s)

Interactive credential prompts

When Neo4j or Aura credentials are missing, the CLI prompts for them interactively on first use and saves them to the config file. To skip prompts in automated or agent contexts, pre-populate credentials via environment variables or the config file.


Agent mode

The CLI is designed to be driven by AI agents, CI pipelines, and orchestration tools. Use --agent (or LOM_AGENT=true) to activate a safe, machine-readable operating mode.

Activating agent mode

# Via flag
lom --agent cloud instances list

# Via environment variable (recommended for pipelines — all invocations inherit it)
export LOM_AGENT=true
lom cloud instances list

What --agent does

Behaviour Human mode (default) Agent mode
Output format table json
Missing credentials Interactive prompt Structured JSON error on stdout, exit non-zero
Errors Written to stderr JSON envelope on stdout
Write operations Allowed with confirmation prompt Blocked unless --rw is also passed

The --rw flag

In agent mode, all operations that modify state are blocked by default. Pass --rw (or LOM_RW=true) to explicitly permit mutations:

# Blocked — returns READ_ONLY error
lom --agent cloud instances delete <id>

# Allowed — no prompt, executes immediately
lom --agent --rw cloud instances delete <id>

--rw governs all mutation categories uniformly:

Category Read operations Write operations (require --rw)
cypher Any read-only query Queries classified as write by Neo4j EXPLAIN
cloud instances list, get create, update, pause, resume, delete
cloud projects list, get (none currently)
admin show-users, show-databases (none currently)
config list set, delete, reset

Cypher write detection

For cypher commands in agent mode without --rw, the CLI automatically runs EXPLAIN on the query before execution. If Neo4j classifies the statement as a write (rw, w, or s), it is blocked:

# EXPLAIN detects a write — blocked
lom --agent cypher "CREATE (n:Person {name:'Alice'}) RETURN n"
# → {"status":"error","error":{"code":"WRITE_BLOCKED","message":"..."},...}

# Read query — EXPLAIN confirms safe, executes
lom --agent cypher "MATCH (n:Person) RETURN n.name LIMIT 10"

# EXPLAIN or PROFILE queries run as-is — no pre-check
lom --agent cypher "EXPLAIN MATCH (n) RETURN n"

With --rw, the EXPLAIN pre-check is skipped and queries execute directly.

Error envelope

All errors in agent mode are written to stdout as a JSON envelope so agents reading stdout get machine-readable failures:

{"status":"error","error":{"code":"READ_ONLY","message":"\"delete\" is a write operation; re-run with --rw to permit mutations"},"request_id":"a1b2c3","schema_version":"1"}

Error codes:

Code Meaning
READ_ONLY Write operation attempted without --rw
WRITE_BLOCKED Cypher write detected by EXPLAIN without --rw
MISSING_QUERY No cypher statement provided in agent mode
MISSING_CREDENTIALS Required credentials absent (no prompt in agent mode)
TIMEOUT Command exceeded --timeout duration
EXECUTION_ERROR Any other failure

Additional agent flags

--request-id string   Correlation ID included in JSON responses.
                      Auto-generated (UUID) if not supplied.
                      Env: LOM_REQUEST_ID

--timeout duration    Maximum time for a command to run (e.g. 30s, 2m).
                      Exit code 1 + TIMEOUT error on expiry.

Recommended orchestrator setup

export LOM_AGENT=true
export LOM_REQUEST_ID="pipeline-run-${RUN_ID}"  # inject your trace ID
export LOM_NEO4J_URI="bolt+s://your-instance.databases.neo4j.io"
export LOM_NEO4J_USERNAME="neo4j"
export LOM_NEO4J_PASSWORD="${NEO4J_PASSWORD}"

# Read operations work with no further flags
lom cypher "MATCH (n:Person) RETURN count(n)"

# Write operations require explicit --rw
lom --rw cypher "CREATE (n:Event {ts: datetime()}) RETURN n"

Contributing

Project structure

cmd/lom/
    main.go             Entry point — calls run() and os.Exit
    app.go              App struct, Cobra root command, startup wiring, flag definitions,
                        subcommand builders (buildCloudCommand, buildCypherCommand, etc.)

internal/
    config/             Config structs, Viper loader, Overrides, SaveConfiguration
    logger/             Logger interface and slog implementation
    analytics/          Mixpanel analytics service
    presentation/       Output formatters (text, JSON, pretty-JSON, table, graph)
    repository/         GraphRepository interface and Neo4j driver implementation
    service/
        interfaces.go       CypherService, CloudService, AdminService interfaces
        cypher_service.go
        cloud_service.go
        admin_service.go
        graph_service.go
    commands/           Category builders (pure wiring — no business logic)
        cypher.go
        cloud.go
        admin.go
        config.go           config list/set/delete/reset category
        prerequisites.go    Neo4jPrerequisite, AuraPrerequisite, interactive variants
    dispatch/           Command routing primitives
        dispatch.go         Registry interface, CommandHandler type, Context struct
        category.go         Category and Command types — Dispatch, Find, SetPrerequisite
    tool/               Tool interface, BaseTool, Context, Result, IOHandler
    tools/              Concrete tool implementations (echo, help, query) + ToolRegistry

The dependency direction is strict:

cmd  →  commands  →  service  →  repository
cmd  →  dispatch
cmd  →  tools
commands  →  dispatch   (for Category / Command / Context types)

No package imports its own parent. dispatch does not import commands or service.


Adding a tool

Tools are flat, named executables registered in the tool registry.

Step 1 — Create the file

Create internal/tools/mytool.go. Embed *tool.BaseTool to get parameter helpers for free:

package tools

import (
    "fmt"
    "github.com/cli/go-cli-tool/internal/tool"
)

type MyTool struct {
    *tool.BaseTool
    prefix string
}

func NewMyTool() *MyTool {
    return &MyTool{
        BaseTool: tool.NewBaseTool(
            "mytool",                        // name — must be unique in the registry
            "Does something interesting",    // description shown in help
            "1.0.0",
        ),
        prefix: ">>",
    }
}

Step 2 — Implement the interface

BaseTool provides no-op defaults for Validate and Configure. Override only the ones you need:

func (t *MyTool) Execute(ctx tool.Context) (tool.Result, error) {
    if len(ctx.Args) == 0 {
        return tool.ErrorResult("usage: mytool <text>"), fmt.Errorf("no input")
    }
    output := fmt.Sprintf("%s %s", t.prefix, ctx.Args[0])
    return tool.SuccessResult(output), nil
}

func (t *MyTool) Validate(ctx tool.Context) error {
    if len(ctx.Args) == 0 {
        return fmt.Errorf("at least one argument is required")
    }
    return nil
}

func (t *MyTool) Configure(params map[string]interface{}) error {
    t.BaseTool.Configure(params) // always call through first
    if v, ok := params["prefix"].(string); ok {
        t.prefix = v
    }
    return nil
}

func (t *MyTool) DefaultParams() map[string]interface{} {
    return map[string]interface{}{"prefix": ">>"}
}

Step 3 — Register it

In cmd/lom/app.go, add your tool to the slice inside buildRegistry:

for _, t := range []tool.Tool{
    tools.NewEchoTool(),
    tools.NewHelpTool(registry),
    tools.NewQueryTool(cypherSvc),
    tools.NewMyTool(),           // ← add here
} {
    registerTool(registry, t, cfg, log)
}

Step 4 — (Optional) Configure via config file

{
  "tools": {
    "mytool": {
      "enabled": true,
      "params": {
        "prefix": "---"
      }
    }
  }
}

Adding a command

A command sits inside an existing category or sub-category. It takes positional arguments and returns a formatted string.

Example: adding admin show-indexes to the admin category

Open internal/commands/admin.go and chain another AddCommand call:

func BuildAdminCategory(svc service.AdminService) *dispatch.Category {
    return dispatch.NewCategory("admin", "Administrative operations...").
        AddCommand(&dispatch.Command{
            Name:        "show-users",
            // ... existing command ...
        }).
        AddCommand(&dispatch.Command{
            Name:        "show-indexes",
            Aliases:     []string{"idx"},
            Usage:       "show-indexes",
            Description: "List all indexes in the current database",
            Handler: func(args []string, ctx dispatch.Context) (string, error) {
                return svc.ShowIndexes(ctx.Context)
            },
        })
}

Aliases are registered automatically in dispatch and appear in parentheses in --help output:

lom admin show-indexes
lom admin idx           # same command

Example: adding a command to a sub-category

To add cloud instances clone <id>, open internal/commands/cloud.go and chain another AddCommand in buildInstancesCategory:

func buildInstancesCategory(svc service.CloudService) *dispatch.Category {
    return dispatch.NewCategory("instances", "Manage Aura DB instances").
        AddCommand(instanceListCmd(svc)).
        // ...existing commands...
        AddCommand(&dispatch.Command{
            Name:        "clone",
            Usage:       "clone <id>",
            Description: "Clone an existing instance",
            Handler: func(args []string, ctx dispatch.Context) (string, error) {
                if len(args) == 0 {
                    return "", fmt.Errorf("usage: cloud instances clone <id>")
                }
                return fmt.Sprintf("Instance %s cloned.", args[0]), nil
            },
        })
}

Adding a category

To add a new top-level category (e.g. gds for Graph Data Science):

Step 1 — Add a service interface

In internal/service/interfaces.go:

type GDSService interface {
    ListAlgorithms(ctx context.Context) ([]string, error)
    RunPageRank(ctx context.Context, graphName string) (string, error)
}

Step 2 — Implement the service

Create internal/service/gds_service.go:

package service

type GDSServiceImpl struct {
    repo repository.GraphRepository
}

func NewGDSService(repo repository.GraphRepository) GDSService {
    return &GDSServiceImpl{repo: repo}
}

func (s *GDSServiceImpl) ListAlgorithms(ctx context.Context) ([]string, error) {
    // CALL gds.list()
    return nil, nil
}

Step 3 — Build the category

Create internal/commands/gds.go:

package commands

import (
    "strings"

    "github.com/cli/go-cli-tool/internal/dispatch"
    "github.com/cli/go-cli-tool/internal/service"
)

func BuildGDSCategory(svc service.GDSService) *dispatch.Category {
    return dispatch.NewCategory("gds", "Graph Data Science operations").
        AddCommand(&dispatch.Command{
            Name:        "list-algorithms",
            Usage:       "list-algorithms",
            Description: "List available GDS algorithms",
            Handler: func(args []string, ctx dispatch.Context) (string, error) {
                algos, err := svc.ListAlgorithms(ctx.Context)
                if err != nil {
                    return "", err
                }
                return strings.Join(algos, "\n"), nil
            },
        })
}

Step 4 — Wire it into App

In cmd/lom/app.go, add the service field, construct it in newApp, and register the category and its Cobra subcommand:

// In newApp(), after repo is created:
gdsSvc := service.NewGDSService(repo)

// In buildCategories():
"gds": commands.BuildGDSCategory(a.gdsSvc).
    SetPrerequisite(commands.InteractiveNeo4jPrerequisite(&a.cfg.Neo4j, a.cfg, configPath)),

// In buildRootCommand():
rootCmd.AddCommand(buildGDSCommand())

func buildGDSCommand() *cobra.Command {
    return &cobra.Command{
        Use:   "gds",
        Short: "Graph Data Science operations",
        RunE:  runCategory("gds"),
        SilenceUsage:  true,
        SilenceErrors: true,
    }
}

Use InteractiveNeo4jPrerequisite for database-connected categories and InteractiveAuraPrerequisite for Aura API categories. Add new prerequisite factories to internal/commands/prerequisites.go if neither fits.

The category is then available as a direct subcommand:

lom gds list-algorithms
lom gds --help

Code conventions

Service pattern — business logic lives in internal/service. Command handlers in internal/commands call services; they contain no logic of their own beyond argument validation and output formatting.

Interfaces before implementations — new behaviour starts with an interface in internal/service/interfaces.go. This keeps the command layer decoupled from concrete implementations and makes testing straightforward.

Prerequisite checks belong in prerequisites.go — if a category requires an external dependency (database connection, API credentials), declare it with SetPrerequisite in buildCategories. Write the factory function in internal/commands/prerequisites.go so it is independently testable. The check runs before every real dispatch, but bare category invocations (e.g. lom cypher --help) always show help regardless.

Tool Validate runs before ExecuteValidate is called automatically before every Execute. Use it for tool-level readiness checks rather than repeating them inside Execute. BaseTool.Validate is a no-op; only override it when needed.

Command aliases are first-class — add short-form names via the Aliases []string field on dispatch.Command. Aliases are resolved in dispatch and shown in --help output. Register the canonical name as Name; aliases are supplementary.

Secrets stay out of flags — passwords and API secrets must not be CLI flags. Accept them only via environment variables, the config file, or interactive prompts.

Errors are the caller's responsibility — return fmt.Errorf("context: %w", err) and let the caller handle it. Don't call os.Exit or log.Fatal from inside a service or command handler.

No imports up the stackdispatch does not import commands or service. commands does not import tools. Keep the dependency graph acyclic and flowing in one direction toward cmd.

Declare MutationMode on every command and tool — every dispatch.Command and tool.Tool must declare its MutationMode. Use ModeRead (default) for read-only operations, ModeWrite for operations that always modify state, and ModeConditional for operations where mutability depends on runtime input (Cypher queries). The dispatcher enforces the read-only contract in agent mode automatically, so individual handlers do not need to check ctx.AgentMode for blocking. Handlers should check ctx.AgentMode only to suppress interactive prompts (e.g. confirmation dialogs).


CI & Releases

One GitHub Actions workflow manages the release process.

Workflows

Workflow Trigger What it does
Release Push of a vX.Y.Z tag Gates on tests, builds cross-platform binaries via GoReleaser, extracts the changelog section, creates a GitHub Release

Making a release

Releases follow a four-step process. changie collects unreleased fragment files and determines the correct semver bump automatically from the change kinds (Added → minor, Fixed/Security → patch, Changed/Removed → major).

1. Batch and merge the changelog

changie batch   # collects .changes/unreleased/*.yaml → .changes/vX.Y.Z.md
changie merge   # folds that file into CHANGELOG.md

2. Commit and tag

git add CHANGELOG.md .changes/
git commit -m "chore: release v0.2.0"
git tag v0.2.0
git push origin main --tags

Adding a changelog entry

Every PR that changes Go source files needs a changie fragment. Run:

changie new

Choose a kind and write a one-line summary, then commit the generated .yaml file alongside your code changes.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

lom-3.2.0-py3-none-win_arm64.whl (19.4 MB view details)

Uploaded Python 3Windows ARM64

lom-3.2.0-py3-none-win_amd64.whl (20.7 MB view details)

Uploaded Python 3Windows x86-64

lom-3.2.0-py3-none-manylinux_2_17_x86_64.whl (20.2 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

lom-3.2.0-py3-none-manylinux_2_17_aarch64.whl (19.2 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

lom-3.2.0-py3-none-macosx_11_0_arm64.whl (19.5 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

lom-3.2.0-py3-none-macosx_10_9_x86_64.whl (20.4 MB view details)

Uploaded Python 3macOS 10.9+ x86-64

File details

Details for the file lom-3.2.0-py3-none-win_arm64.whl.

File metadata

  • Download URL: lom-3.2.0-py3-none-win_arm64.whl
  • Upload date:
  • Size: 19.4 MB
  • Tags: Python 3, Windows ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.13

File hashes

Hashes for lom-3.2.0-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 76abef6136c8446fd6b4c57e0b3106a4fe094611e1ba1279c45e9a9e56eb6abf
MD5 c9627e71f7174c4fbdd8ace22faf7214
BLAKE2b-256 de9cd0548d30f285173e76f51a44e998a01495f4c7349a67b605ec77182305a5

See more details on using hashes here.

File details

Details for the file lom-3.2.0-py3-none-win_amd64.whl.

File metadata

  • Download URL: lom-3.2.0-py3-none-win_amd64.whl
  • Upload date:
  • Size: 20.7 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.13

File hashes

Hashes for lom-3.2.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 56749151161c0afbc3e810fb0e6be42ff098d14287b156a2d16cf613b7b63cb3
MD5 cee1c089f04efaa5b0ee744f46bd67c5
BLAKE2b-256 1f0bedd6db608a05cde61f710828f0f4a0b6380e7a8beda09b4076c937aff733

See more details on using hashes here.

File details

Details for the file lom-3.2.0-py3-none-manylinux_2_17_x86_64.whl.

File metadata

  • Download URL: lom-3.2.0-py3-none-manylinux_2_17_x86_64.whl
  • Upload date:
  • Size: 20.2 MB
  • Tags: Python 3, manylinux: glibc 2.17+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.13

File hashes

Hashes for lom-3.2.0-py3-none-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 85b9a3c742e0d43cf249529f2aaea8d81a7686be6d3372180ca0842b4ed1a477
MD5 60a7b2cf30ba5eb5a65e536d1bac820c
BLAKE2b-256 8d61d316ec2ba1f0458af39ddbe29738545af0098985638dcb63adeb56b4fae8

See more details on using hashes here.

File details

Details for the file lom-3.2.0-py3-none-manylinux_2_17_aarch64.whl.

File metadata

  • Download URL: lom-3.2.0-py3-none-manylinux_2_17_aarch64.whl
  • Upload date:
  • Size: 19.2 MB
  • Tags: Python 3, manylinux: glibc 2.17+ ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.13

File hashes

Hashes for lom-3.2.0-py3-none-manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 56edd108042fdfbb9404b48265d55826b318a69d24694ea8da07adb409e88195
MD5 ed88a61fda43501a33399e78a95f7d1b
BLAKE2b-256 f9c8d81b2c94a2140531cbd7fdf34e6c18346a388c5a4a9aa6030034b28fd526

See more details on using hashes here.

File details

Details for the file lom-3.2.0-py3-none-macosx_11_0_arm64.whl.

File metadata

  • Download URL: lom-3.2.0-py3-none-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 19.5 MB
  • Tags: Python 3, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.13

File hashes

Hashes for lom-3.2.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 25621dd69e308b863201e01a1f82dfa42449d8890e0d22b5fbdc03704929175c
MD5 0a20aa56f3e409fba99f54f4a8923c76
BLAKE2b-256 089d120453879b6b0c426e713fc847300283a948fa14cdb9b09f0ce7eff8a413

See more details on using hashes here.

File details

Details for the file lom-3.2.0-py3-none-macosx_10_9_x86_64.whl.

File metadata

  • Download URL: lom-3.2.0-py3-none-macosx_10_9_x86_64.whl
  • Upload date:
  • Size: 20.4 MB
  • Tags: Python 3, macOS 10.9+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.13

File hashes

Hashes for lom-3.2.0-py3-none-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 c3e9a003ded0410f47ca1531a14aadd14f40d5aa58cee0139ee48e6fbfbdb72a
MD5 d7212d2c0729616002ee60d19eb8f513
BLAKE2b-256 a01ed7ce3909c0dc2b476499d450a7fdd27e01ed14ebb2392cfad0e666c19890

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page