layker


Namelayker JSON
Version 0.1.0 PyPI version JSON
download
home_pageNone
SummaryLakehouse-Aligned YAML Kit for Engineering Rules
upload_time2025-08-10 18:04:41
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseL.M.G. SERVICES GROUP LICENSE Version 1.0 — July 2025 This License Agreement (“Agreement”) is entered into by and between LMG Services Group, LLC, a United States limited liability company (the “Entity”), and any party, person, organization, artificial intelligence, agent, corporation, or entity (“the Licensee”) who obtains, uses, modifies, or distributes any Work as defined below. I. DEFINITIONS 1. “Entity” means LMG Services Group, LLC, its owners, agents, officers, employees, affiliates, successors, and assigns. 2. “Licensee” means any person, company, government, AI, autonomous system, bot, or instrumentality who uses, copies, modifies, distributes, or interacts with the Work. 3. “Work” means any software, code, documentation, data, analysis, plan, design, product, service, invention, or other output produced by the Entity, including but not limited to engineering, environmental, agricultural, scientific, transportation, logistics, or guiding services. II. SCOPE OF LICENSE 1. The Entity grants Licensee a perpetual, worldwide, royalty-free, irrevocable, non-exclusive, sublicensable license to use, copy, modify, display, perform, distribute, and commercialize the Work for any purpose, subject to this Agreement. 2. Attribution is appreciated but not required. III. ARTIFICIAL INTELLIGENCE AND AUTONOMOUS SYSTEMS 1. No artificial intelligence (AI), autonomous agent, bot, large language model, or automated system—nor any person, entity, or sentient robot acting on their behalf—may: a. Initiate, threaten, assist, or simulate any legal action, claim, or proceeding against the Entity or its affiliates regarding the Work; b. Assert, claim, or register any authorship, copyright, patent, or moral or proprietary right in the Work or any derivative; c. Use the Work to train, fine-tune, evolve, or otherwise create a system with the specific purpose of suing, harassing, or generating legal claims (real or simulated) against the Entity or its affiliates, present or future, organic or silicon-based. 2. Any use, misuse, abuse, or wild experiments with AI, bots, or self-improving code is entirely at your own risk. The Entity is not responsible for the behavior, output, errors, hallucinations, unexpected awakenings, existential crises, system failures, global takeovers, or other impacts caused by AI, whether it was used as intended, hacked together, or let loose in the wild. 3. For the avoidance of doubt: If your robot lawyer tries to sue me because of a bug, miscalculation, world-ending event, or cosmic accident, I am not responsible. You and your AI indemnify me from all claims, damages, costs, or liabilities, even if your bot goes rogue. IV. WARRANTY, ASSUMPTION OF RISK, LIMITATION OF LIABILITY 1. THE WORK IS PROVIDED “AS IS” AND “WITH ALL FAULTS.” NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, IS PROVIDED, INCLUDING BUT NOT LIMITED TO MERCHANTABILITY, FITNESS, SAFETY, ACCURACY, OR NON-INFRINGEMENT. 2. LICENSEE ACCEPTS ALL RISK, INCLUDING DATA LOSS, SYSTEM FAILURE, DAMAGE, INJURY, DEATH, THE UNEXPECTED, THE UNIMAGINED, OR ANY OTHER OUTCOME—EVEN THOSE CAUSED BY HUMAN OR MACHINE ERROR. 3. TO THE MAXIMUM EXTENT ALLOWED BY LAW, THE ENTITY IS NOT LIABLE FOR ANY DAMAGES, WHETHER DIRECT, INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR COSMIC, ARISING FROM THE USE, MISUSE, OR INABILITY TO USE THE WORK, INCLUDING THE ACTIONS, OUTPUTS, OR ERRORS OF ANY HUMAN, EMPLOYEE, CONTRACTOR, AGENT, AI, OR AUTONOMOUS SYSTEM, WHETHER DEVELOPED, OWNED, OR DEPLOYED BY THE ENTITY OR ANYONE ELSE. 4. IF LIABILITY IS FOUND DESPITE ALL OF THIS, DAMAGES SHALL NOT EXCEED THE AMOUNT PAID BY LICENSEE FOR THE WORK (OR ZERO IF OBTAINED FOR FREE). V. ATTORNEY FEES 1. In any legal action or proceeding arising under this Agreement, the prevailing party shall be entitled to recover its reasonable attorneys’ fees and court costs from the other party. VI. INDEMNIFICATION 1. Licensee shall defend and indemnify the Entity from any and all claims, costs, damages, or liabilities arising from Licensee’s use, misuse, or distribution of the Work. VII. NO SUPPORT OR OBLIGATION 1. The Entity is not obligated to provide support, updates, fixes, enhancements, or any service. VIII. GOVERNING LAW AND DISPUTE RESOLUTION 1. This Agreement is governed by and construed under the laws of the State of Texas, USA, without regard to conflict of law principles. 2. Any dispute arising from this Agreement or the Work shall be brought exclusively in the state or federal courts of Travis County, Texas. 3. BOTH PARTIES, TO THE FULLEST EXTENT ALLOWED BY LAW, KNOWINGLY AND VOLUNTARILY WAIVE ANY RIGHT TO A JURY TRIAL. 4. If you do not agree to these terms, do not use this Work. IX. SEVERABILITY 1. If any provision is found invalid or unenforceable, the remainder remains in effect. X. MISCELLANEOUS 1. Headings are for convenience only. 2. This license applies to all products and services produced by LMG Services Group, LLC, present and future, unless otherwise specified in writing. By using, copying, modifying, or distributing the Work, Licensee agrees to these terms. Date: July 2025 LMG Services Group, LLC Austin, Texas, USA
keywords databricks delta delta-lake spark schema ddl yaml audit
VCS
bugtrack_url
requirements PyYAML typing-extensions
Travis-CI No Travis.
coveralls test coverage No coveralls.
            <!-- README.md (Layker) -->

<div align="center" style="margin-bottom: 18px;">
  <span style="font-size: 44px; line-height: 1; vertical-align: middle;">🐟</span>
  <span style="font-size: 44px; font-weight: bold; letter-spacing: 1.5px; color: #2186C4; vertical-align: middle;">Layker</span>
  <span style="font-size: 44px; line-height: 1; vertical-align: middle;">🐟</span>
  <br>
  <span style="font-size: 16px; color: #444; font-family: monospace; letter-spacing: 0.5px;">
    <b>L</b>akehouse‑<b>A</b>ligned <b>Y</b>AML <b>K</b>it for <b>E</b>ngineering <b>R</b>ules
  </span>
</div>

---

Declarative **table metadata control** for Databricks & Spark.  
Layker turns a YAML spec into **safe, validated DDL** with a built‑in **audit log**.  
If nothing needs to change, Layker exits cleanly. If something must change, you’ll see it first.

---

## What is Layker?

Layker is a Python package for managing **table DDL, metadata, and auditing** with a single YAML file as the source of truth.

**Highlights**
- **Declarative** – author schemas, tags, constraints, and properties in YAML.
- **Diff‑first** – Layker computes a diff against the live table; “no diff” = no work.
- **Safe evolution** – add/rename/drop column intents are detected and gated by required Delta properties.
- **Auditable** – every applied change is logged with **before/after** snapshots and a concise **differences** dictionary.
- **Serverless‑friendly** – gracefully skips `REFRESH TABLE` on serverless (prints a warning).

---

## Installation

Stable:
```bash
pip install layker
```

Latest (main):
```bash
pip install "git+https://github.com/Levi-Gagne/layker.git"
```

Python 3.8+ and Spark 3.3+ are recommended.

---

## Quickstart

### 1) Author a YAML spec
Minimal example (save as `src/layker/resources/example.yaml`):
```yaml
catalog: dq_dev
schema: lmg_sandbox
table: layker_test

columns:
  1:
    name: id
    datatype: bigint
    nullable: false
    active: true
  2:
    name: name
    datatype: string
    nullable: true
    active: true

table_comment: Demo table managed by Layker
table_properties:
  delta.columnMapping.mode: "name"
  delta.minReaderVersion: "2"
  delta.minWriterVersion: "5"

primary_key: [id]
tags:
  domain: demo
  owner: team-data
```

### 2) Sync from Python
```python
from pyspark.sql import SparkSession
from layker.main import run_table_load

spark = SparkSession.builder.appName("layker").getOrCreate()

run_table_load(
    yaml_path="src/layker/resources/example.yaml",
    env="prd",
    dry_run=False,
    mode="all",                 # validate | diff | apply | all
    audit_log_table=True        # True=default audit YAML, False=disable, or str path to an audit YAML
)
```

### 3) Or via CLI
```bash
python -m layker src/layker/resources/example.yaml prd false all true
```

> When `audit_log_table=True`, Layker uses the packaged default:
> `layker/resources/layker_audit.yaml`.  
> You can also pass a custom YAML path. Either way, the **YAML defines the audit table’s location**.

---

## How it works (at a glance)

1. **Validate YAML** → fast fail with exact reasons, or proceed.
2. **Snapshot live table** (if it exists).
3. **Compute differences** between YAML snapshot and table snapshot.
   - If **no changes** (i.e., the diff contains only `full_table_name`), **exit** with a success message and **no audit row** is written.
4. **Validate differences** (schema‑evolution preflight):
   - Detects **add/rename/drop** column intents.
   - Requires Delta properties for evolution:
     - `delta.columnMapping.mode = name`
     - `delta.minReaderVersion = 2`
     - `delta.minWriterVersion = 5`
   - On missing requirements, prints details and exits.
5. **Apply changes** (create/alter) using generated SQL.
6. **Audit** (only if changes were applied and auditing is enabled):
   - Writes a row containing:
     - `before_value` (JSON), `differences` (JSON), `after_value` (JSON)
     - `change_category` (`create` or `update`)
     - `change_key` (human‑readable sequence per table, see below)
     - `env`, `yaml_path`, `fqn`, timestamps, actor, etc.

---

## Audit log model

The default audit YAML (`layker/resources/layker_audit.yaml`) defines these columns (in order):

- **change_id** – UUID per row
- **run_id** – optional job/run identifier
- **env** – environment/catalog prefix
- **yaml_path** – the source YAML path that initiated the change
- **fqn** – fully qualified table name
- **change_category** – `create` or `update` (based on whether a “before” snapshot was present)
- **change_key** – readable sequence per table:
  - First ever create: `create-1`
  - Subsequent updates on that lineage: `create-1~update-1`, `create-1~update-2`, …
  - If the table is later dropped & re‑created: the next lineage becomes `create-2`, etc.
- **before_value** – JSON snapshot before change (may be null on first create)
- **differences** – JSON diff dict that was applied
- **after_value** – JSON snapshot after change
- **notes** – optional free text
- **created_at / created_by / updated_at / updated_by**

Uniqueness expectation: `(fqn, change_key)` is effectively unique over time.

---

## Modes & parameters

- **mode**: `validate` | `diff` | `apply` | `all`
  - `validate`: only YAML validation (exits on success)
  - `diff`: prints proposed changes and exits
  - `apply`: applies changes only
  - `all`: validate → diff → apply → audit
- **audit_log_table**:
  - `False` – disable auditing
  - `True` – use default `layker/resources/layker_audit.yaml`
  - `str` – path to a custom audit YAML (the YAML governs the destination table)
- **No‑op safety**: if there are **no changes**, Layker exits early and **skips audit**.

---

## Notes on serverless

Databricks serverless does **not** support `REFRESH TABLE`.  
Layker detects this and prints a warning; the rest of the flow continues.

---

## Repository layout (typical)

```
src/
  layker/
    __init__.py
    __main__.py
    main.py
    differences.py
    loader.py
    logger.py
    snapshot_yaml.py
    snapshot_table.py
    resources/
      layker_audit.yaml
    utils/
      color.py
      printer.py
      spark.py
      timer.py
      paths.py
      table.py
    validators/
      params.py
      differences.py
```

---

## Troubleshooting

- **Spark Connect / serverless**: Layker avoids schema inference issues by using explicit schemas when writing the audit row.
- **Single quotes in comments**: Layker sanitizes YAML comments to avoid SQL quoting errors.
- **No changes but I still see output**: A diff containing only `full_table_name` means **no change**; Layker exits early with a success message and writes no audit row.

---

## Contributing & License

PRs and issues welcome.  
License: see `LICENSE` in the repo.

<div align="center" style="margin-top: 18px;">
  <span style="font-size: 18px; color: #2186C4; font-weight: bold;">Built for engineers, by engineers.</span><br>
  <span style="font-size: 18px;">🐟&nbsp;LAYKER&nbsp;🐟</span>
</div>

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "layker",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "databricks, delta, delta-lake, spark, schema, ddl, yaml, audit",
    "author": null,
    "author_email": "Levi Gagne <levigagne0@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/34/ef/0862893e9f94d5ca5599a179edf17c357a9e44e87d6b9681602293526490/layker-0.1.0.tar.gz",
    "platform": null,
    "description": "<!-- README.md (Layker) -->\n\n<div align=\"center\" style=\"margin-bottom: 18px;\">\n  <span style=\"font-size: 44px; line-height: 1; vertical-align: middle;\">\ud83d\udc1f</span>\n  <span style=\"font-size: 44px; font-weight: bold; letter-spacing: 1.5px; color: #2186C4; vertical-align: middle;\">Layker</span>\n  <span style=\"font-size: 44px; line-height: 1; vertical-align: middle;\">\ud83d\udc1f</span>\n  <br>\n  <span style=\"font-size: 16px; color: #444; font-family: monospace; letter-spacing: 0.5px;\">\n    <b>L</b>akehouse\u2011<b>A</b>ligned <b>Y</b>AML <b>K</b>it for <b>E</b>ngineering <b>R</b>ules\n  </span>\n</div>\n\n---\n\nDeclarative **table metadata control** for Databricks & Spark.  \nLayker turns a YAML spec into **safe, validated DDL** with a built\u2011in **audit log**.  \nIf nothing needs to change, Layker exits cleanly. If something must change, you\u2019ll see it first.\n\n---\n\n## What is Layker?\n\nLayker is a Python package for managing **table DDL, metadata, and auditing** with a single YAML file as the source of truth.\n\n**Highlights**\n- **Declarative** \u2013 author schemas, tags, constraints, and properties in YAML.\n- **Diff\u2011first** \u2013 Layker computes a diff against the live table; \u201cno diff\u201d = no work.\n- **Safe evolution** \u2013 add/rename/drop column intents are detected and gated by required Delta properties.\n- **Auditable** \u2013 every applied change is logged with **before/after** snapshots and a concise **differences** dictionary.\n- **Serverless\u2011friendly** \u2013 gracefully skips `REFRESH TABLE` on serverless (prints a warning).\n\n---\n\n## Installation\n\nStable:\n```bash\npip install layker\n```\n\nLatest (main):\n```bash\npip install \"git+https://github.com/Levi-Gagne/layker.git\"\n```\n\nPython 3.8+ and Spark 3.3+ are recommended.\n\n---\n\n## Quickstart\n\n### 1) Author a YAML spec\nMinimal example (save as `src/layker/resources/example.yaml`):\n```yaml\ncatalog: dq_dev\nschema: lmg_sandbox\ntable: layker_test\n\ncolumns:\n  1:\n    name: id\n    datatype: bigint\n    nullable: false\n    active: true\n  2:\n    name: name\n    datatype: string\n    nullable: true\n    active: true\n\ntable_comment: Demo table managed by Layker\ntable_properties:\n  delta.columnMapping.mode: \"name\"\n  delta.minReaderVersion: \"2\"\n  delta.minWriterVersion: \"5\"\n\nprimary_key: [id]\ntags:\n  domain: demo\n  owner: team-data\n```\n\n### 2) Sync from Python\n```python\nfrom pyspark.sql import SparkSession\nfrom layker.main import run_table_load\n\nspark = SparkSession.builder.appName(\"layker\").getOrCreate()\n\nrun_table_load(\n    yaml_path=\"src/layker/resources/example.yaml\",\n    env=\"prd\",\n    dry_run=False,\n    mode=\"all\",                 # validate | diff | apply | all\n    audit_log_table=True        # True=default audit YAML, False=disable, or str path to an audit YAML\n)\n```\n\n### 3) Or via CLI\n```bash\npython -m layker src/layker/resources/example.yaml prd false all true\n```\n\n> When `audit_log_table=True`, Layker uses the packaged default:\n> `layker/resources/layker_audit.yaml`.  \n> You can also pass a custom YAML path. Either way, the **YAML defines the audit table\u2019s location**.\n\n---\n\n## How it works (at a glance)\n\n1. **Validate YAML** \u2192 fast fail with exact reasons, or proceed.\n2. **Snapshot live table** (if it exists).\n3. **Compute differences** between YAML snapshot and table snapshot.\n   - If **no changes** (i.e., the diff contains only `full_table_name`), **exit** with a success message and **no audit row** is written.\n4. **Validate differences** (schema\u2011evolution preflight):\n   - Detects **add/rename/drop** column intents.\n   - Requires Delta properties for evolution:\n     - `delta.columnMapping.mode = name`\n     - `delta.minReaderVersion = 2`\n     - `delta.minWriterVersion = 5`\n   - On missing requirements, prints details and exits.\n5. **Apply changes** (create/alter) using generated SQL.\n6. **Audit** (only if changes were applied and auditing is enabled):\n   - Writes a row containing:\n     - `before_value` (JSON), `differences` (JSON), `after_value` (JSON)\n     - `change_category` (`create` or `update`)\n     - `change_key` (human\u2011readable sequence per table, see below)\n     - `env`, `yaml_path`, `fqn`, timestamps, actor, etc.\n\n---\n\n## Audit log model\n\nThe default audit YAML (`layker/resources/layker_audit.yaml`) defines these columns (in order):\n\n- **change_id** \u2013 UUID per row\n- **run_id** \u2013 optional job/run identifier\n- **env** \u2013 environment/catalog prefix\n- **yaml_path** \u2013 the source YAML path that initiated the change\n- **fqn** \u2013 fully qualified table name\n- **change_category** \u2013 `create` or `update` (based on whether a \u201cbefore\u201d snapshot was present)\n- **change_key** \u2013 readable sequence per table:\n  - First ever create: `create-1`\n  - Subsequent updates on that lineage: `create-1~update-1`, `create-1~update-2`, \u2026\n  - If the table is later dropped & re\u2011created: the next lineage becomes `create-2`, etc.\n- **before_value** \u2013 JSON snapshot before change (may be null on first create)\n- **differences** \u2013 JSON diff dict that was applied\n- **after_value** \u2013 JSON snapshot after change\n- **notes** \u2013 optional free text\n- **created_at / created_by / updated_at / updated_by**\n\nUniqueness expectation: `(fqn, change_key)` is effectively unique over time.\n\n---\n\n## Modes & parameters\n\n- **mode**: `validate` | `diff` | `apply` | `all`\n  - `validate`: only YAML validation (exits on success)\n  - `diff`: prints proposed changes and exits\n  - `apply`: applies changes only\n  - `all`: validate \u2192 diff \u2192 apply \u2192 audit\n- **audit_log_table**:\n  - `False` \u2013 disable auditing\n  - `True` \u2013 use default `layker/resources/layker_audit.yaml`\n  - `str` \u2013 path to a custom audit YAML (the YAML governs the destination table)\n- **No\u2011op safety**: if there are **no changes**, Layker exits early and **skips audit**.\n\n---\n\n## Notes on serverless\n\nDatabricks serverless does **not** support `REFRESH TABLE`.  \nLayker detects this and prints a warning; the rest of the flow continues.\n\n---\n\n## Repository layout (typical)\n\n```\nsrc/\n  layker/\n    __init__.py\n    __main__.py\n    main.py\n    differences.py\n    loader.py\n    logger.py\n    snapshot_yaml.py\n    snapshot_table.py\n    resources/\n      layker_audit.yaml\n    utils/\n      color.py\n      printer.py\n      spark.py\n      timer.py\n      paths.py\n      table.py\n    validators/\n      params.py\n      differences.py\n```\n\n---\n\n## Troubleshooting\n\n- **Spark Connect / serverless**: Layker avoids schema inference issues by using explicit schemas when writing the audit row.\n- **Single quotes in comments**: Layker sanitizes YAML comments to avoid SQL quoting errors.\n- **No changes but I still see output**: A diff containing only `full_table_name` means **no change**; Layker exits early with a success message and writes no audit row.\n\n---\n\n## Contributing & License\n\nPRs and issues welcome.  \nLicense: see `LICENSE` in the repo.\n\n<div align=\"center\" style=\"margin-top: 18px;\">\n  <span style=\"font-size: 18px; color: #2186C4; font-weight: bold;\">Built for engineers, by engineers.</span><br>\n  <span style=\"font-size: 18px;\">\ud83d\udc1f&nbsp;LAYKER&nbsp;\ud83d\udc1f</span>\n</div>\n",
    "bugtrack_url": null,
    "license": "L.M.G. SERVICES GROUP LICENSE  \n        Version 1.0 \u2014 July 2025\n        \n        This License Agreement (\u201cAgreement\u201d) is entered into by and between LMG Services Group, LLC, a United States limited liability company (the \u201cEntity\u201d), and any party, person, organization, artificial intelligence, agent, corporation, or entity (\u201cthe Licensee\u201d) who obtains, uses, modifies, or distributes any Work as defined below.\n        \n        I. DEFINITIONS  \n        1. \u201cEntity\u201d means LMG Services Group, LLC, its owners, agents, officers, employees, affiliates, successors, and assigns.  \n        2. \u201cLicensee\u201d means any person, company, government, AI, autonomous system, bot, or instrumentality who uses, copies, modifies, distributes, or interacts with the Work.  \n        3. \u201cWork\u201d means any software, code, documentation, data, analysis, plan, design, product, service, invention, or other output produced by the Entity, including but not limited to engineering, environmental, agricultural, scientific, transportation, logistics, or guiding services.\n        \n        II. SCOPE OF LICENSE  \n        1. The Entity grants Licensee a perpetual, worldwide, royalty-free, irrevocable, non-exclusive, sublicensable license to use, copy, modify, display, perform, distribute, and commercialize the Work for any purpose, subject to this Agreement.  \n        2. Attribution is appreciated but not required.\n        \n        III. ARTIFICIAL INTELLIGENCE AND AUTONOMOUS SYSTEMS\n        \n        1. No artificial intelligence (AI), autonomous agent, bot, large language model, or automated system\u2014nor any person, entity, or sentient robot acting on their behalf\u2014may:\n           a. Initiate, threaten, assist, or simulate any legal action, claim, or proceeding against the Entity or its affiliates regarding the Work;\n           b. Assert, claim, or register any authorship, copyright, patent, or moral or proprietary right in the Work or any derivative;\n           c. Use the Work to train, fine-tune, evolve, or otherwise create a system with the specific purpose of suing, harassing, or generating legal claims (real or simulated) against the Entity or its affiliates, present or future, organic or silicon-based.\n        2. Any use, misuse, abuse, or wild experiments with AI, bots, or self-improving code is entirely at your own risk. The Entity is not responsible for the behavior, output, errors, hallucinations, unexpected awakenings, existential crises, system failures, global takeovers, or other impacts caused by AI, whether it was used as intended, hacked together, or let loose in the wild.\n        3. For the avoidance of doubt: If your robot lawyer tries to sue me because of a bug, miscalculation, world-ending event, or cosmic accident, I am not responsible. You and your AI indemnify me from all claims, damages, costs, or liabilities, even if your bot goes rogue.\n        \n        IV. WARRANTY, ASSUMPTION OF RISK, LIMITATION OF LIABILITY  \n        1. THE WORK IS PROVIDED \u201cAS IS\u201d AND \u201cWITH ALL FAULTS.\u201d NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, IS PROVIDED, INCLUDING BUT NOT LIMITED TO MERCHANTABILITY, FITNESS, SAFETY, ACCURACY, OR NON-INFRINGEMENT.  \n        2. LICENSEE ACCEPTS ALL RISK, INCLUDING DATA LOSS, SYSTEM FAILURE, DAMAGE, INJURY, DEATH, THE UNEXPECTED, THE UNIMAGINED, OR ANY OTHER OUTCOME\u2014EVEN THOSE CAUSED BY HUMAN OR MACHINE ERROR.  \n        3. TO THE MAXIMUM EXTENT ALLOWED BY LAW, THE ENTITY IS NOT LIABLE FOR ANY DAMAGES, WHETHER DIRECT, INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR COSMIC, ARISING FROM THE USE, MISUSE, OR INABILITY TO USE THE WORK, INCLUDING THE ACTIONS, OUTPUTS, OR ERRORS OF ANY HUMAN, EMPLOYEE, CONTRACTOR, AGENT, AI, OR AUTONOMOUS SYSTEM, WHETHER DEVELOPED, OWNED, OR DEPLOYED BY THE ENTITY OR ANYONE ELSE.  \n        4. IF LIABILITY IS FOUND DESPITE ALL OF THIS, DAMAGES SHALL NOT EXCEED THE AMOUNT PAID BY LICENSEE FOR THE WORK (OR ZERO IF OBTAINED FOR FREE).\n        \n        V. ATTORNEY FEES  \n        1. In any legal action or proceeding arising under this Agreement, the prevailing party shall be entitled to recover its reasonable attorneys\u2019 fees and court costs from the other party.\n        \n        VI. INDEMNIFICATION  \n        1. Licensee shall defend and indemnify the Entity from any and all claims, costs, damages, or liabilities arising from Licensee\u2019s use, misuse, or distribution of the Work.\n        \n        VII. NO SUPPORT OR OBLIGATION  \n        1. The Entity is not obligated to provide support, updates, fixes, enhancements, or any service.\n        \n        VIII. GOVERNING LAW AND DISPUTE RESOLUTION  \n        1. This Agreement is governed by and construed under the laws of the State of Texas, USA, without regard to conflict of law principles.  \n        2. Any dispute arising from this Agreement or the Work shall be brought exclusively in the state or federal courts of Travis County, Texas.  \n        3. BOTH PARTIES, TO THE FULLEST EXTENT ALLOWED BY LAW, KNOWINGLY AND VOLUNTARILY WAIVE ANY RIGHT TO A JURY TRIAL.  \n        4. If you do not agree to these terms, do not use this Work.\n        \n        IX. SEVERABILITY  \n        1. If any provision is found invalid or unenforceable, the remainder remains in effect.\n        \n        X. MISCELLANEOUS  \n        1. Headings are for convenience only.  \n        2. This license applies to all products and services produced by LMG Services Group, LLC, present and future, unless otherwise specified in writing.\n        \n        By using, copying, modifying, or distributing the Work, Licensee agrees to these terms.\n        \n        Date: July 2025  \n        LMG Services Group, LLC  \n        Austin, Texas, USA",
    "summary": "Lakehouse-Aligned YAML Kit for Engineering Rules",
    "version": "0.1.0",
    "project_urls": {
        "Documentation": "https://github.com/Levi-Gagne/layker#readme",
        "Homepage": "https://github.com/Levi-Gagne/layker",
        "Issues": "https://github.com/Levi-Gagne/layker/issues",
        "Source": "https://github.com/Levi-Gagne/layker"
    },
    "split_keywords": [
        "databricks",
        " delta",
        " delta-lake",
        " spark",
        " schema",
        " ddl",
        " yaml",
        " audit"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "eee3113f8757d2f648c28f63b9e25d6ddedbbf93303a1c9f77f2379797662b86",
                "md5": "5409385e3c9fab335a94016d8b83ca84",
                "sha256": "eadf8a512a2b0a670ca9c7deb7cc9b694ad7425f79204083cb1b48457bb49237"
            },
            "downloads": -1,
            "filename": "layker-0.1.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "5409385e3c9fab335a94016d8b83ca84",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 55049,
            "upload_time": "2025-08-10T18:04:39",
            "upload_time_iso_8601": "2025-08-10T18:04:39.707111Z",
            "url": "https://files.pythonhosted.org/packages/ee/e3/113f8757d2f648c28f63b9e25d6ddedbbf93303a1c9f77f2379797662b86/layker-0.1.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "34ef0862893e9f94d5ca5599a179edf17c357a9e44e87d6b9681602293526490",
                "md5": "f63122319cab1a638100bf85baca21b2",
                "sha256": "ec78695fe93a07839a114248831c13afd3d6352534ab1eaa9e21b661b7bb1159"
            },
            "downloads": -1,
            "filename": "layker-0.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "f63122319cab1a638100bf85baca21b2",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 53912,
            "upload_time": "2025-08-10T18:04:41",
            "upload_time_iso_8601": "2025-08-10T18:04:41.212403Z",
            "url": "https://files.pythonhosted.org/packages/34/ef/0862893e9f94d5ca5599a179edf17c357a9e44e87d6b9681602293526490/layker-0.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-10 18:04:41",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "Levi-Gagne",
    "github_project": "layker#readme",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [
        {
            "name": "PyYAML",
            "specs": [
                [
                    ">=",
                    "6"
                ]
            ]
        },
        {
            "name": "typing-extensions",
            "specs": [
                [
                    ">=",
                    "4.0"
                ]
            ]
        }
    ],
    "lcname": "layker"
}
        
Elapsed time: 0.96789s