Skip to main content

A hierarchical, state-inheriting command and request builder.

Project description

logo

Slug Farm

Status: “Works for me” beta, pre-alpha ideation for basically everyone else.
For my personal centralized task scheduling, this is effectively beta (it does what I need).
For a broader audience / general-purpose library use, it’s early alpha at best, and honestly closer to pre-alpha ideation.


“Slug”

Package gets its name because the original idea was to boil any granule of functionality to string(the slug, in a strict sense) a command, and kwargs.

  • The object is a Slug (or BashSlug, RequestSlug, etc.).
  • The slug (conceptually) is the name used to address that object inside a registry.

So the “slug” is ultimately the registry key, which is a slug in the strict sense for the functionality


What this is

Slug Farm is a framework for reducing disparate kinds of work into one callable shape:

result = some_slug(command="...", task_kwargs={...})

There is also a SlugRegistry which holds these slugs further abstrating the slug to an identifiable string

result is intended to always be a SlugResult

Core Use Case

I built this for centralized task scheduling, where I want to call tasks across REST APIs and shell environments etc. This allows me to keep tasks in a database in an easily patchable form. I can also define large collections of tasks quickly by “walking” through and capturing all viable intermediates as functions, which is especially helpful with bash-like command structures or API endpoint trees.

The real value is persistence + uniformity:

Any task becomes: (slug name (str), command (str), kwargs (dict))


Discovered Benefit

Once you get the hang of it, declarating a tree of functions is quite streamlined and readable. I've been able to write python functions for a tree RestAPI endpoints in a way that is clear to understand and maps quite cleanly to the APIs Swagger documentation.

The Challenge

To support this minimal branching declaration

If you’re thinking:

  • “I need a way to call a bunch of operations”
  • “I want structured access to a set of endpoints”
  • “I want composable function calls”

…then again: a dictionary of functions is probably better.
It’s simpler, clearer, easier to type-check, easier to debug, and WAYY less opinionated.

The “juice” you get from Slug Farm is real, but the “squeeze” is learning a structure that is necessarily rigid and ultimitely quite arbitrary.


What’s in here right now

BashSlug

Builds a command + flags list and executes with subprocess.

  • Intentionally does not interpret pipes or shell operators.
  • Literal | is treated as an argument, not an operator (this is a security decision).

RequestSlug

Builds an HTTP request using requests, with inherited URL segments, params merging, and JSON-body logic.

  • Supports placeholders like /crops/{crop_name}. Which can be "intelligently" (hopefully) replaced with kwargs during call
  • GET carries params; POST/PUT/PATCH carry params and JSON bodies (with filtering support).

UDP_Slug

Sends UDP payloads (optionally in bursts) with a shared UUID per run.

PythonSlug

Wraps a Python callable so it fits the same (command, task_kwargs) invocation style. This exist entirely if you're benefitting heavily from the SlugRegistry for Bash and Request and would like use the same structure for Python slugs. This would be quite silly to use in a vacuum.


Registry (the part that makes the naming make sense)

The registry concept is the “why” behind the name Slug Farm:

  • the Slug object is the implementation
  • the slug name is the address (registry key)
  • the registry is what makes tasks easy to store/replay/patch

Right now:

  • A SlugRegistry exists, but it’s not fully built out into the persistence-oriented system I want.
  • I still need to expand this area and add tests around it.
  • YAML declarative registry would be cool. Ways to inject custom slug classes into declarative yaml are being currently mulled over.

Installation

pip install slug_farm

From source:

git clone <repo>
cd SlugFarm
pip install -e ".[dev]"

Quickstart

BashSlug (dry run)

from slug_farm import BashSlug

git = BashSlug(name = "git", command = "git")
status = git.branch(branch_name = "status", command="status")

result = status(task_kwargs = {'untracked-status': 'no', 's': True})  # executes "git status -s --untracked-status no"

RequestSlug (dry run)

from slug_farm import RequestSlug

api = RequestSlug(
    name = "api", 
    base_url="https://example.com/v1", 
    headers = SOME_HEADERS_DEFINED_ELSEWHERE
)
crops = api.branch(  # Inherits headers, params, etc. Default method is GET
    branch_name = "crops", 
    url_segment="crops"
)

get_result = crops(task_kwargs={"limit": 10})

add_crops = crops.branch(
    branch_name= "add",
    url_segment="add",
    method="POST"
)

add_crops(task_kwargs = {"apples": 10}) # Sends a post request to https://example.com/v1/crops/add, presumably to add 10 apples.

 # Here is where shoehorning RestAPI requests into (command, kwargs)-only structure adds some clunk.  
 # exclude_params makes sure the crop_id param isn't passed and is only swapped in the url placeholder
 # If the endpoint is okay getting it as a param too you don't need to bother
get_specific = crops.branch(
    branch_name = "specific",
    url_segment="{crop_id}",
    exclude_params="crop_id"
)

get_specific(task_kwargs = {"crop_id": "crop_2b67d"}) # Sends a GET request to https://example.com/v1/crops/crop_2b67d, utilizing the placeholder

UDP_Slug

from slug_farm import UDP_Slug

slug = UDP_Slug(
    "telemetry",
    url="127.0.0.1",
    port=9999,
    burst_size=5, # Will send a burst of 5 identical messages.  All messages within burst will contain the same uuid4 so the listener can deduplicate.
    burst_delay_ms=50,
)

result = slug(task_kwargs={"hello": "world"}) # Command arg is generally excluded.  If you include it to UDP it adds a "message" key and puts your command there.  Should probably just be "command" though. Looking into it eventually
print(result.ok, result.status)

Contributing / expectations

If you’re looking at this repo with a “could this be useful?” mindset:

PRs and tests are welcome, especially around:

  • registry behavior
  • persistence patterns
  • clearer docs/examples
  • Intelligent and clear error messages.
    • With a structure this opinionated, error messages should be able to be incredibly readable and informative without making it more opinionated to support that. This does not exist yet.
  • logging integration
  • edge-case safety
  • Declarative initiation and hydration
    • Again, one of the benefits of being opinionated is that a 'suite' of slugs might be able to be declared with a simple yaml file, or automatically collected from a script. This could even potentially be procedurally generated from a Swagger page.
    • Hydrating a slug registry from a YAML also offers the opportunity to pre-inspect a config and surface some more errors/hints of such an opinionated library in a way which is difficult to do with docstrings/linting alone.

License

MIT. See LICENSE.

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

slug_farm-0.1.1.tar.gz (85.4 kB view details)

Uploaded Source

Built Distribution

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

slug_farm-0.1.1-py3-none-any.whl (14.9 kB view details)

Uploaded Python 3

File details

Details for the file slug_farm-0.1.1.tar.gz.

File metadata

  • Download URL: slug_farm-0.1.1.tar.gz
  • Upload date:
  • Size: 85.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for slug_farm-0.1.1.tar.gz
Algorithm Hash digest
SHA256 1513f2783a91d0c0a16fdb11583c234ce3a9190365b3c22fe134c1a99b891b0f
MD5 acd6f7ee5b0c2a1bd2188db221c984b9
BLAKE2b-256 a51ac5f555e9b650ff70cfbbd12d3c04368a5cbaf7880f958ce51368b55ffb8d

See more details on using hashes here.

File details

Details for the file slug_farm-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: slug_farm-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 14.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for slug_farm-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ecb525cc9d8f85e116a271fad106111fb3fd92f4b339070a33e9fbbda1ea50ba
MD5 823e9a5016167efb7795ddd656c91afa
BLAKE2b-256 a006535ba642f5828aab5b39cc04f712c2ed59cecd9ee8450a6716a99baca5be

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