Skip to main content

A refined, full scale solution to CLIs .

Project description

Active Development CI Test Status License: GPL v3 PyPI Downloads coverage

end.

endpoint is a refined, full scale solution to CLIs .

Compatibility

🟩 (Works perfectly); 🟨 (Untested); 🟧 (Some Issues); 🟥 (Unusable)

OS
Windows 🟩
MacOS 🟩
Linux (Ubuntu 22.04 LTS) 🟩

Features

  • Easy to use for beginners, but not lacking for experts
  • Efficient
  • Fully cross-platform
  • Regular updates and support
  • Comprehensive documentation

Installation

You can install endpoint via pip:

pip install endpoint.cli --pre --upgrade

Or clone the repository and install manually:

git clone https://github.com/Adalfarus/endpoint-py.git
cd endpoint-py
python -m pip install .

If you have problems with the package please use py -m pip install endpoint.cli[dev] --pre --upgrade --user

📦 Usage

The examples below are grouped by capability so you can copy only what you need.

1. Route commands with Interface

from endpoint.interface import Interface


def hello(name: str = "world") -> None:
    print(f"hello {name}")


app = Interface("my-cli", default_endpoint_or_message="Unknown command")
app.path("greet", hello, "Print a greeting")
app.path("math::sum", lambda a: print(sum(map(int, a))), "Sum integers")

# Simulate: my-cli greet --name Ada
app.parse_cli(["my-cli", "greet", "--name", "Ada"], skip_first_arg=True)

2. Build endpoints from function signatures

from endpoint.endpoints import NativeEndpoint
from endpoint.native_parser import NativeParser


def deploy(env: str, *, dry_run: bool = False, retries: int = 1) -> None:
    """Deploy app.
    env: Deployment target.
    dry_run: Validate only.
    retries: Retry count.
    """
    print(env, dry_run, retries)


endpoint = NativeEndpoint.from_function(
    deploy,
    name="deploy",
    parser=NativeParser({}),
)

# Simulate: deploy production --dry-run --retries 3
endpoint.parse(["deploy", "production", "--dry-run", "--retries", "3"], skip_first_arg=True)

3. Define arguments manually (all core knobs)

from endpoint.endpoints import NativeEndpoint
from endpoint.native_parser import NativeParser, NArgsMode, NArgsSpec, ArgumentParsingError


def run(input_file: str, **kwargs) -> None:
    print(input_file, kwargs)


ep = NativeEndpoint("run", "Manual argument model", function=run, parser=NativeParser({}))

ep.add_argument("input_file", types=[str], positional_only=True, required=True, help_="Input path")
ep.add_argument("count", types=[int], default=1, choices=[1, 2, 3], help_="How many times")
ep.add_argument("verbose", types=[bool], default=False, help_="Enable verbose output")
ep.add_argument("tags", types=[list[str]], default=[], nargs=NArgsMode.ZERO_OR_MORE(NArgsSpec.MANY))
ep.add_argument("mode", types=[str], default="safe", kwarg_only=True, help_="Execution mode")

def validate_count(arg, value):
    if value < 1:
        return ArgumentParsingError("count must be >= 1")
    return value

ep.change_argument("count", checking_func=validate_count)
ep.guess_letters_and_shortforms()

# Simulate: run file.txt --count 2 --verbose --mode fast --tags a,b
ep.parse(["run", "file.txt", "--count", "2", "--verbose", "--mode", "fast", "--tags", "a,b"], skip_first_arg=True)

4. Wrap endpoint invocation (logging, timing, tracing, auth)

from endpoint.endpoints import NativeEndpoint


def add(a: int, b: int) -> int:
    return a + b


def wrapper(endpoint, fn, *args, **kwargs):
    print(f"calling {endpoint!r} with {args=} {kwargs=}")
    return fn(*args, **kwargs)


ep = NativeEndpoint.from_function(add, "add")
ep.set_calling_func(wrapper)
ep.parse(["add", "2", "3"], skip_first_arg=True)

5. Use parser backends

NativeEndpoint accepts any parser implementing Parser.

from endpoint.endpoints import NativeEndpoint
from endpoint.native_parser import NativeParser
from endpoint.parser_collection import LightParser, TokenStreamParser, StrictDFAParser, FastParser, TinyParser


def task(value: int, flag: bool = False) -> None:
    print(value, flag)


NativeEndpoint.from_function(task, "native", parser=NativeParser({}))
NativeEndpoint.from_function(task, "light", parser=LightParser({}))
NativeEndpoint.from_function(task, "stream", parser=TokenStreamParser({"repeatable_collections": True}))
NativeEndpoint.from_function(task, "dfa", parser=StrictDFAParser({}))
NativeEndpoint.from_function(task, "fast", parser=FastParser({"FAST_ALLOW_POSITIONALS": True}))
NativeEndpoint.from_function(task, "tiny", parser=TinyParser({}))

6. Use ArgparseEndpoint when you want argparse behavior

from endpoint.endpoints import ArgparseEndpoint


ep = ArgparseEndpoint(prog="my-cli", description="Argparse-backed endpoint")
ep.add_argument("--value", type=int, required=True)
ep.set_calling_func(lambda *, value: print(value))

ep.parse(["my-cli", "--value", "5"], skip_first_arg=True, automatic_help_args=())

7. Convert native endpoint definitions to argparse

from endpoint.endpoints import NativeEndpoint


ep = NativeEndpoint.from_function(lambda count=1: print(count), "tool")
argparse_parser = ep.to_argparse()
argparse_ep = ep.to_argparse_endpoint()

ns = argparse_parser.parse_args(["--count", "3"])
print(ns.count)

_, parsed = argparse_ep.parse(["tool", "--count", "3"], skip_first_arg=True, automatic_help_args=())
print(parsed["count"])

8. Inspect callables and types

from endpoint.functional import analyze_function, get_analysis, break_type, pretty_type


def sample(a: int, b: str = "x") -> bool:
    """sample function"""
    return True


print(analyze_function(sample))
print(get_analysis(sample).to_dict())
print(break_type(list[int]))
print(pretty_type(dict[str, int]))

9. Build command trees manually

from endpoint.structure import Structure, add_command_to_structure, structure_help
from endpoint.endpoints import NativeEndpoint


tree = Structure("demo")
add_command_to_structure("ops::health", "Check health", NativeEndpoint("health"), tree)
add_command_to_structure("ops::version", "Show version", NativeEndpoint("version"), tree)
print(structure_help(tree["demo"]))

10. Project CLI entrypoint

The package installs endpoint-cli for project workflows:

endpoint-cli help
endpoint-cli tests run tests/ --minimal

Naming convention, dependencies and library information

PEP 8 -- Style Guide for Python Code

For modules I use 'lowercase', classes are 'CapitalizedWords' and functions and methods are 'lower_case_with_underscores'.

Contributing

We welcome contributions! Please see our contributing guidelines for more details on how you can contribute to endpoint.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a pull request

Aps Build master

You can use the aps_build_master script for your os to make your like a lot easier. It supports running tests, installing, building and much more as well as chaining together as many commands as you like.

This example runs test, build the project and then installs it

Windows:

call .\aps_build_master.bat 234

Unix:

sudo apt install python3-pip
sudo apt install python3-venv
chmod +x ./aps_build_master.sh
./aps_build_master.sh 234

License

endpoint is licensed under the GPL-3.0 License - see the LICENSE file for details.

Project details


Download files

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

Source Distribution

endpoint_cli-2.1.1.2.tar.gz (83.8 kB view details)

Uploaded Source

Built Distribution

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

endpoint_cli-2.1.1.2-py3-none-any.whl (88.8 kB view details)

Uploaded Python 3

File details

Details for the file endpoint_cli-2.1.1.2.tar.gz.

File metadata

  • Download URL: endpoint_cli-2.1.1.2.tar.gz
  • Upload date:
  • Size: 83.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.25

File hashes

Hashes for endpoint_cli-2.1.1.2.tar.gz
Algorithm Hash digest
SHA256 2c2ca05a127a69c9498fd1659d11b08ea2c2e390b70846626a378e23e19c66a1
MD5 0e95494d078edc01718367bfb7893926
BLAKE2b-256 e4d98e6b4fc2750d267fb03bd99bff760afe779ef10ab8cbfd989c8be8550e45

See more details on using hashes here.

File details

Details for the file endpoint_cli-2.1.1.2-py3-none-any.whl.

File metadata

  • Download URL: endpoint_cli-2.1.1.2-py3-none-any.whl
  • Upload date:
  • Size: 88.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.25

File hashes

Hashes for endpoint_cli-2.1.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 784081414ec8a5bd7512c5c161e339f0f5edb37040cf17bdd52972d1975d1ba2
MD5 5e6a73ce4ece837cb271c103e6f34102
BLAKE2b-256 65e97a87a2f6f49b5f7cae4a5c8909cfaf4bae2fe972df4b7166c40f7ca570c0

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