Skip to main content

Gnarly

Gnarly is a pretty-printer for RDF 1.2, used for serializing Turtle, TriG, and related RDF syntaxes.

Usage

Install from source or PyPI (e.g. using pip). Gnarly is written in Python and uses pyoxigraph for parsing RDF.

Pass files or pipe to the CLI:

$ gnarly test/data/test-gnarly.trig

(See gnarly -h for all options.)

Pretty-Printing Turtle/TriG

By default, Turtle/TriG is written with the following features:

  • Uses given prefixes to compact IRIs into PNames,
  • optional base IRI to shorten IRIs;
  • group descriptions by subject,
  • writes types first, on subject line if short enough, then
  • predicates separated by semicolon, and
  • multiple objects, separated by comma; with support for
  • nested blank nodes,
  • compact lists (with one line per item for longer values),
  • boolean keywords, pure floats and doubles, and compact triple terms;
  • compact forms of reifiers (including multiple and named reifiers), and
  • compact annotations on asserted triples (including multiple and named annotations);
  • takes multiple references into account and avoids blank node cycles.

Example Output

prefix : <https://example.net/ns/>
prefix ctg: <https://example.net/ns/category/>

<https://example.org/a> a :Thing ;
  :category ctg:CommonThings ;
  :name "A" ;
  :references <https://example.org/b> ,
    <https://example.org/c> ;
  :value 1 ,
    "a" .

<https://example.org/b> a :Thing ;
  :category ctg:Regular ;
  :references [ a :Thing ;
      :name "C" ;
      :references [
          :category ctg:Special ;
          :name "D" ;
          :references [ :name "E" ]
        ]
    ] .

<https://example.org/c>
  :items ( <https://example.org/b> <https://example.org/c> ) ;
  :referenceList (
      <https://example.org/b>
      <https://example.org/c>
      <https://example.org/d>
      <https://example.org/e>
    ) ;
  :valueList ( 1 "a" ) .

<https://example.org/d> :references <https://example.org/c> .

Formatting Options

There are different style conventions for Turtle/TriG. Gnarly has options to tweak some things to adhere to different preferences.

The default settings are:

  • Indent: 2 spaces
  • Max column: 88 characters

There are three named styles, exemplified here with differences in output:

Modern

This is the default, described above.

prefix : <https://example.net/ns/>

<https://example.org/a> a :Thing ;
  :references <https://example.org/b> ,
    [ a :Thing ;
      :name "C" ;
      :references [
          :name "D" ;
          :references [ :name "E" ]
        ]
    ] ;
  :value 1 ,
    "a" .

Classic

This form is more compact, but at the expense of readability for deeply nested blank nodes, and/or annotations. It also uses the classic, @-sigil for prefix and base, no explicit graph keyword, and no padding space before ;, ,, and . separators.

@prefix : <https://example.net/ns/>.

<https://example.org/a> a :Thing;
  :references <https://example.org/b>,
    [ a :Thing;
      :name "C";
      :references [
          :name "D";
          :references [ :name "E" ] ] ];
  :value 1,
    "a".

Longhand

Puts predicates, including types, on new lines, and ends all statement lines with semicolon; ending a subject description with a period on its own line. Uses uppercase SPARQL keywords.

This style is useful for rapid copy&paste editing and line-based diffs:

PREFIX : <https://example.net/ns/>

<https://example.org/a>
  a :Thing ;
  :references <https://example.org/b> ;
  :references [
      a :Thing ;
      :name "C" ;
      :references [
          :name "D" ;
          :references [ :name "E" ] ;
        ] ;
    ] ;
  :value 1 ;
  :value "a" ;
.

Detailed Formatting

The following examples are serialized using the default formatting options. (Many are variations on examples in the main RDF 1.2 Primer.)

# Prefixes are sorted, and declared using lowercase SPARQL-style syntax by default:

prefix : <http://example.net/ns/>
prefix dcterms: <http://purl.org/dc/terms/>
prefix foaf: <http://xmlns.com/foaf/0.1/>
prefix lio: <http://purl.org/net/lio#>
prefix prov: <http://www.w3.org/ns/prov#>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
prefix wd: <http://www.wikidata.org/entity/>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>

# Types are written on the subject line:

<http://example.org/bob#me> a foaf:Person ;
  foaf:birthday "1990-07-04"^^xsd:date ;
  foaf:knows <http://example.org/alice#me> .

# Multiple triples are written under the subject:

wd:Q12418
  dcterms:creator <http://dbpedia.org/resource/Leonardo_da_Vinci> ;
  dcterms:title "Mona Lisa" .

# Single statements and simple embedded blank nodes are kept on one line:

wd:Q12418 dcterms:creator <http://dbpedia.org/resource/Leonardo_da_Vinci> .

wd:Q12418 lio:shows [ a <http://dbpedia.org/resource/Cypress> ] .

# Long lines also result in line breaks:

<http://data.europeana.eu/item/04802/243FA8618938F4117025F17A8B813C5F9AA4D619>
  dcterms:subject wd:Q12418 .

<http://dbpedia.org/resource/Mona_Lisa> lio:shows [
      a <http://dbpedia.org/resource/Cypress> ] .

# A single blank annotation is written as:

<http://example.org/bob#me> a foaf:Person ;
  foaf:topic_interest wd:Q12418 {| a rdf:Statement ;
        dcterms:creator <http://example.org/alice#me> ;
        dcterms:date "2004-01-12"^^xsd:date
      |} .

# and a named annotation like:

<http://example.org/bob#me> a foaf:Person ;
  foaf:topic_interest wd:Q12418 ~ <http://example.org/alice#claim-1> .

# Multiple annotations are written beneath the statement:

<http://example.org/bob#me> a foaf:Person ;
  foaf:topic_interest wd:Q12418
      {| a rdf:Statement ;
        dcterms:creator <http://example.org/alice#me> ;
        dcterms:date "2004-01-12"^^xsd:date
      |}
      {| a prov:Influence ;
        dcterms:date "1998-10-04"^^xsd:date
      |} .

# As are multiple named annotations:

<http://example.org/bob#me> a foaf:Person ;
  foaf:topic_interest wd:Q12418
      ~ <http://example.org/alice#claim-1>
      ~ <http://example.org/bob#interest-1> .

<http://example.org/alice#claim-1> a rdf:Statement ;
  dcterms:creator <http://example.org/alice#me> ;
  dcterms:date "2004-01-12"^^xsd:date .

<http://example.org/bob#interest-1> a prov:Influence ;
  dcterms:date "1998-10-04"^^xsd:date .

# As shown in the example output above, lists are written on one or multiple lines, depending on resulting width:

<https://example.org/c>
  :items ( <https://example.org/b> <https://example.org/c> ) ;
  :referenceList (
      <https://example.org/b>
      <https://example.org/c>
      <https://example.org/d>
      <https://example.org/e>
    ) ;
  :valueList ( 1 "a" [ :value "b" ] ) .

Maintenance

Simple round-trip run of local examples, and (optionally) the official RDF Turtle/TriG tests:

$ ./test.sh clone/of/w3c/rdf-tests  # from <https://github.com/w3c/rdf-tests>

Metadata

Release files for gnarly 0.1.1

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

Source distribution (sdist)

Source distribution for gnarly 0.1.1
File Size Uploaded Provenance
gnarly-0.1.1.tar.gz 13.9 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for gnarly 0.1.1
File Interpreter ABI Platform
gnarly-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 31.2 kB

Release files / gnarly-0.1.1.tar.gz

Download URL gnarly-0.1.1.tar.gz
Size 13.9 kB
Tags Source
SHA-256 checksum
How to use checksums
1d010fd6c444c55bc76d9af61ee047996f0d2939cedaa01d176ff31a932f92c1
BLAKE2b-256 checksum
How to use checksums
02efed29351177e6971637e5059bc0b9e4befadc25a2635b070f64bab6b0dc43
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.

Transparency log

Release files / gnarly-0.1.1-py3-none-any.whl

Download URL gnarly-0.1.1-py3-none-any.whl
Size 17.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
86fd45146f42b3a36623beecc87234213f48cdc7b0f3e07e18aa32bf1cc8ef42
BLAKE2b-256 checksum
How to use checksums
611dd1bb0bdc9e086f7cdf0622de325ddc9c6ad1a51b19f693264e890f01bd88
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.

Transparency log

Security for gnarly 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for gnarly-0.1.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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