Links Notation Parser for Python
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)
Working with Link Objects
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; withcomments=Falsea#is an ordinary character instead of the start of a commentparse(input_text: str) -> List[Link]: Parse Links Notation text into Link objects
Link
Represents a link in Links Notation.
__init__(id: Optional[str] = None, values: Optional[List[Link]] = None)format(less_parentheses: bool = False) -> str: Format as stringsimplify() -> Link: Simplify link structurecombine(other: Link) -> Link: Combine with another link
format_links
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.
Links
Release files for links-notation 0.21.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| links_notation-0.21.1.tar.gz | 39.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| links_notation-0.21.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 60.1 kB
Release files / links_notation-0.21.1.tar.gz
| Download URL | links_notation-0.21.1.tar.gz |
|---|---|
| Size | 39.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
14fe79056ed88fb37bc550f44946c94c667d548c33994926bad576b8857d44a8
|
|
BLAKE2b-256 checksum How to use checksums |
6c4c1a53c727ecda29004885c2f6083852a2813f24a11dfa3ffa225ddd7b0ee9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / links_notation-0.21.1-py3-none-any.whl
| Download URL | links_notation-0.21.1-py3-none-any.whl |
|---|---|
| Size | 20.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3baaacb00ba385ad8054c91645c582a3c3fc64311b1af763dffda066f04479a6
|
|
BLAKE2b-256 checksum How to use checksums |
aaa292591fd1ac4aa2d2395a67c23cc9f75bf87b00024cb54460374b4ff99141
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|