Skip to main content

Links Notation Parser for Python

PyPI version Python versions License

Python implementation of the Links Notation parser.

Installation

pip install links-notation

Quick Start

from links_notation import Parser

parser = Parser()
links = parser.parse("papa (lovesMama: loves mama)")

# Access parsed links
for link in links:
    print(link)

Usage

Basic Parsing

from links_notation import Parser, format_links

parser = Parser()

# Parse simple links
links = parser.parse("(papa: loves mama)")
print(links[0].id)  # 'papa'
print(len(links[0].values))  # 2

# Format links back to string
output = format_links(links)
print(output)  # (papa: loves mama)
from links_notation import Link

# Create links programmatically
link = Link('parent', [Link('child1'), Link('child2')])
print(str(link))  # (parent: child1 child2)

# Access link properties
print(link.id)  # 'parent'
print(link.values[0].id)  # 'child1'

# Combine links
combined = link.combine(Link('another'))
print(str(combined))  # ((parent: child1 child2) another)

Indented Syntax

parser = Parser()

# Parse indented notation
text = """3:
  papa
  loves
  mama"""

links = parser.parse(text)
# Produces: (3: papa loves mama)

Streaming Parsing

StreamParser accepts arbitrary chunks and emits only complete top-level records. Set collect=False for bounded-memory callback or generator use.

from links_notation import StreamParser, parse_chunks

stream = StreamParser(on_link=print, collect=False)
stream.write("profile:\n  name Ada\n")
stream.finish("next link")

for link in parse_chunks(["one li", "nk\ntwo link"]):
    print(link)

parse_async_chunks provides the equivalent native async generator. The stream also exposes position, drain(), reset(), and a buffer-size limit.

API Reference

Parser

The main parser class for Links Notation.

  • __init__(..., comments: bool = True): Create a parser; with comments=False a # is an ordinary character instead of the start of a comment
  • parse(input_text: str) -> List[Link]: Parse Links Notation text into Link objects

Represents a link in Links Notation.

  • __init__(id: Optional[str] = None, values: Optional[List[Link]] = None)
  • format(less_parentheses: bool = False) -> str: Format as string
  • simplify() -> Link: Simplify link structure
  • combine(other: Link) -> Link: Combine with another link

Format a list of links into Links Notation.

  • format_links(links: List[Link], less_parentheses: bool = False) -> str

Examples

Doublets (2-tuple)

parser = Parser()
text = """
papa (lovesMama: loves mama)
son lovesMama
daughter lovesMama
"""
links = parser.parse(text)

Triplets (3-tuple)

text = """
papa has car
mama has house
(papa and mama) are happy
"""
links = parser.parse(text)

Quoted References

# References with special characters need quotes
text = '("has space": "value with: colon")'
links = parser.parse(text)

Multi-line Groups

A parenthesized group opens a nested context: its body starts fresh at indentation level zero and follows the same rules as the root document, so a line break inside parentheses is structure rather than decoration.

value (
  id "1"
  label "one"
)

The document above parses to (value ((id 1) (label one))) - two children, each a link of its own - rather than to one flat list in which the boundary between id and label would be lost. A body that stays on a single line still collapses to a single link, so (a b c) is unchanged.

text = """value (
  id "1"
  label "one"
)"""
print(format_links(parser.parse(text)))
# (value ((id 1) (label one)))

Comments

A # hides the rest of the line it stands on, so a document can carry prose about itself:

# the machines this deploys to
deploy: staging # only staging, for now

Both comments are gone by the time the document is read, leaving the single link (deploy: staging). A # only opens a comment where a reference could begin, so a # inside a token (issue#1047) and a # inside a delimited reference ("#") stay ordinary characters.

A formatter keeps the same rule from the other side: a reference that begins with a # is written quoted ('#tag'), so a document it writes reads back as itself.

Comments are on by default, and a parser can be told to read # as an ordinary character again, for documents written before comments existed:

document = "# the machines this deploys to\ndeploy: staging # only staging, for now\n"
print(format_links(Parser().parse(document)))  # (deploy: staging)

print(format_links(Parser(comments=False).parse("# a b\n")))  # (# a b)

Development

Running Tests

# Install development dependencies
pip install pytest

# Run tests
pytest

Building

pip install build
python -m build

Maintenance

Linting and Formatting

This project uses Black for code formatting, isort for import sorting, and flake8 for linting.

Install linting tools:

pip install ".[lint]"
# Or install all dev dependencies
pip install ".[dev]"

Format all code files

black .
isort .

Check formatting (without modifying files)

black --check --diff .
isort --check-only --diff .
flake8 --max-line-length=120

These checks are enforced in CI. Pull requests with unformatted code will fail the lint check.

Pre-commit Hooks

This project uses pre-commit hooks that automatically run Black, isort, and flake8 before commits. To set up pre-commit hooks locally:

# From repository root
pip install pre-commit
pre-commit install

License

This project is released into the public domain under the Unlicense.

Release files for links-notation 0.20.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for links-notation 0.20.0
File Size Uploaded
links_notation-0.20.0.tar.gz 39.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for links-notation 0.20.0
File Interpreter ABI Platform
links_notation-0.20.0-py3-none-any.whl Python 3 none any Details

Total release size: 59.5 kB

Release history Release notifications | RSS feed

0.21.3

2 release files

0.21.2

2 release files

0.21.1

2 release files

0.21.0

2 release files

This release

0.20.0 This release

2 release files

0.16.1

2 release files

0.16.0

2 release files

0.15.0

2 release files

0.14.0

2 release files

0.12.0

2 release files

0.11.2

2 release files

0.11.0

2 release files

0.10.0

2 release files

0.9.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page