dndc, but from python
Project description
DND --- David's Novel Documents
A Better Way to Write
.dnd files are a convenient way to write documents, create dungeons, record notes, and other things that you would like to write prose or free-form text, but with a little more structure. .dnd files offer unrivaled ability to introspect the document for a document format.At its heart, .dnd is a tree-based language. Blocks are actually composable and can have different parse rules, which is useful for embedding other languages within a document. Normally, a block is designated by indentation and ends when either the document ends or a block with less indentation is introduced. A new block is normally introduced by a block containing two colons. For example:
Hello World!::md This is some wonderful text!
In the above example, a block is introduced on the first line. The text to the left of the double colon is the "header" of the block. For documents, this is used as text for a heading. It is optional. The text to the right of the double colon is the block's type, in this case "md". The type must be one recognized by the compiling program and changes the parsing rules for the subsequent block.
On the next line, we indent as the string is a child of the md block. One of the rules for md blocks is that consecutive lines of text will be combined together into paragraph nodes. A blank line indicates the end of a paragraph. Md blocks can also embed other blocks, which are introduced in the usual manner by double colons.
The above snippet will be translated into the following:
Hello World!
This is some wonderful text!
Which looks like:
Hello World!
This is some wonderful text!
The exact level of the heading will depend on where the block is in the final document tree. Parent blocks with headings will increase the level of child headings. Blocks at root scope with headings will be h2s.
Convenience
The most convenient type of block to write in is the "md" block. It is not a markdown block, but it is similar in some ways. Notably missing are markdown style headers. We offer the 'h' block instead, or just nest another md block.For example:
I am so smart::md It is really amazing how smart I am. Behold my intelligence: 1. My IQ is over 9000. 2. I am really good looking. * This is an important point. * Wait, what does that have to do with intelligence? This is an internal heading::h Yeah, what about it? An internal block::md This is what I usually use instead as it mirrors how I think about the topic (subtopic is a subtree).
Turns into this:
I am so smart
It is really amazing how smart I am. Behold my intelligence:
- My IQ is over 9000.
-
I am really good looking.
- This is an important point.
- Wait, what does that have to do with intelligence?
This is an internal heading
Yeah, what about it?
An internal block
This is what I usually use instead as it mirrors how I think about the topic (subtopic is a subtree).
Additionally we support tables. For example:
::comment This is a comment by the way! It is not in the rendered html. The first row of the table is taken to be the headings for the table. There is no requirement to have the same number of cells in each row, but user beware, it gets wonky. The Nodes::table Node Type | Block Name | Heading MD | md | Yes DIV | div | Yes STRING | --- | --- PARA | --- | --- TITLE | title | Yes HEADING | h | Yes TABLE | table | Yes TABLE_ROW | --- | --- STYLESHEETS | css | --- LINKS | links | --- SCRIPTS | script | --- IMPORT | import | --- IMAGE | img | Yes BULLETS | --- | Yes RAW | raw | No PRE | pre | Yes LIST | --- | Yes LIST_ITEM | --- | No KEYVALUE | kv | Yes KEYVALUEPAIR | --- | No IMGLINKS | imglinks | Yes TOC | toc | Yes COMMENT | comment | --- CONTAINER | --- | No QUOTE | quote | Yes JS | js | No DETAILS | details | Yes INVALID | --- | --- ::md * Node Type is the type of the node. * Block name is how it is introduced via the double colon syntax (an empty entry indicates the node can only be created via scripts or implicitly as part of another node). * Heading is whether or not the header is turned into a heading. * The INVALID node will cause an error if encountered during rendering. It can be used as a poison node when debugging. For more detailed information, see the [reference](REFERENCE.html). ::links reference = REFERENCE.html
And here is that table
The Nodes
Node Type | Block Name | Heading |
---|---|---|
MD | md | Yes |
DIV | div | Yes |
STRING | --- | --- |
PARA | --- | --- |
TITLE | title | Yes |
HEADING | h | Yes |
TABLE | table | Yes |
TABLE_ROW | --- | --- |
STYLESHEETS | css | --- |
LINKS | links | --- |
SCRIPTS | script | --- |
IMPORT | import | --- |
IMAGE | img | Yes |
BULLETS | --- | Yes |
RAW | raw | No |
PRE | pre | Yes |
LIST | --- | Yes |
LIST_ITEM | --- | No |
KEYVALUE | kv | Yes |
KEYVALUEPAIR | --- | No |
IMGLINKS | imglinks | Yes |
TOC | toc | Yes |
COMMENT | comment | --- |
CONTAINER | --- | No |
QUOTE | quote | Yes |
JS | js | No |
DETAILS | details | Yes |
INVALID | --- | --- |
- Node Type is the type of the node.
- Block name is how it is introduced via the double colon syntax (an empty entry indicates the node can only be created via scripts or implicitly as part of another node).
- Heading is whether or not the header is turned into a heading.
- The INVALID node will cause an error if encountered during rendering. It can be used as a poison node when debugging.
For more detailed information, see the reference.
Self-Contained
.dnd documents can include css and js files. They will be placed into the head of the document so that the html page is completely self-contained. However, you don't have to write them inline here in one document. You can include them in the document by the appropriate block.Example:
::comment You haven't seen this before. The '#' symbol to the right of the double colon indicates a directive. Only certain directives are allowed. For example, this #import directive tells the system to not interpret the contents as raw strings to be included in a <script> tag, but instead as file paths to load. css blocks also support #import with the same meaning, but for <style>. ::css #import cssfile1.css another/css/file.css and/another.css ::script #import somejsfile.js another/jsfile.js ::css * { box-sizing: border-box; }
Images can also be included. They are base64-encoded and stored as a data
string in the html page. You can use the #noinline
directive
to disable this behavior.
Attributes, Classes and Directives
Blocks can have classes, which directly correspond to css classes in the output html.Example:
Hola::div .foo .bar hello, aloha
In this example the Hola div will have foo
and bar
as css classes.
Blocks can also have attributes, which are user defined tags. They only have whatever meaning you give to them.
Example:
A room::md @coord(1,2) some stuff is in the room Another room::md @coord(4, 6) A goblin is in this room.
A block can have any number of attributes. Attributes are identifiers and can have arguments in parens. The contents of the parens are stored as a string.
Javascript blocks can retrieve the attributes of a node via the .attributes field. It presents a map-like interface to the attributes. You can also set an attribute without a value, which will give it an empty string as its value. Many things only check for the presence of the key and ignore the value.
Directives
Blocks can also have directives, which are prefixed by the '#'.Example:
Don't look::div #hide Don't put me in the document! Duplicate Heading::h #id(my-id) Duplicate Heading::h #id(my-id-2) Don't ID me bro::md #noid IDs are for squares!
The following directives are currently used.
Attribute | Meaning |
---|---|
`#noid` | Don't give the heading an id |
`#id(iden)` | Instead of the automatic id, use `iden` as the id for the heading |
`#hide` | Don't output the block in the rendered output. |
`#noinline` | Produce a link (href) instead of embedding. |
`#import` | Treat the lines inside the block as paths to be imported and import them as children of this node. |
Directives may be expanded in future versions.
But Wait, There's More
The structured document format is convenient to write in, but sometimes you need to manipulate the document programmatically. Javascript blocks are your friend.For Example:
::js ` js blocks have 3 special variables in them. node: this node (the js block) ctx: this variable represents the state of compiling. It offers methods such as \`make_node\` to create new nodes that can be inserted into the document. NodeType: This is actually a do-nothing object, that is used to namespace the types of the nodes. This is useful because you need to choose a type if you make a new node. You can also check the \`type\` attribute on nodes. ` for(let child of node.parent.children){ if(child.type == NodeType.PARA){ for(let line of child.children){ if(line.header.includes('example')) line.header = 'For Example:'; } } if(child.type == NodeType.PRE){ child.add_child('::js'); for(let line of node.children){ child.add_child(' '+line.header); } break; } } // If you're paying attention, you'll realize this js block added itself // to the document.
Javascript blocks are isolated.
You can print things in javascript blocks, using console.log
. I
used it several times while writing this!
::js ` This block will print out every node in the document. The system can do this as well more efficiently, but this is just showing off that io works as expected. ` function walk(n, depth){ if(depth > 10){ return; } console.log('--'.repeat(depth), n); for(let child of n.children){ walk(child, depth+1); } } walk(ctx.root, 0);
Here is a fun demo. We will now embed the entire document via javascript. This is all done at compile time. You can even see the javascript block that was used to embed the text.
This Document
DND --- David's Novel Documents::title A Better Way to Write::md .dnd files are a convenient way to write documents, create dungeons, record notes, and other things that you would like to write prose or free-form text, but with a little more structure. .dnd files offer unrivaled ability to introspect the document for a document format.At its heart, .dnd is a tree-based language. Blocks are actually composable and can have different parse rules, which is useful for embedding other languages within a document. Normally, a block is designated by indentation and ends when either the document ends or a block with less indentation is introduced. A new block is normally introduced by a block containing two colons. For example:
::pre .embedded Hello World!::md This is some wonderful text! In the above example, a block is introduced on the first line. The text to the left of the double colon is the "header" of the block. For documents, this is used as text for a heading. It is optional. The text to the right of the double colon is the block's type, in this case "md". The type must be one recognized by the compiling program and changes the parsing rules for the subsequent block.
On the next line, we indent as the string is a child of the md block. One of the rules for md blocks is that consecutive lines of text will be combined together into paragraph nodes. A blank line indicates the end of a paragraph. Md blocks can also embed other blocks, which are introduced in the usual manner by double colons.
The above snippet will be translated into the following:
::pre .embedded
::comment Comments look like this. You would only notice this if you were reading this from the source demo down below.Hello World!
This is some wonderful text!
The raw block fixes the indentation, but otherwises pastes the strings as is into the resulting document. This is an escape hatch and allows you to do arbitrary things that don't deserve special syntax. For example, if you want to embed an input form then you are no longer writing prose, so it is fine if you just write some raw html. Most nodes that contain other nodes will either have a <div> tag or will have the appropriate tag for that kind of node (for example, a pre node will have a <pre> tag.) The raw node is one of the exceptions to this.
Which looks like:
::div .embedded ::raw
The exact level of the heading will depend on where the block is in the final document tree. Parent blocks with headings will increase the level of child headings. Blocks at root scope with headings will be h2s.Hello World!
This is some wonderful text!
Convenience::md The most convenient type of block to write in is the "md" block. It is not a markdown block, but it is similar in some ways. Notably missing are markdown style headers. We offer the 'h' block instead, or just nest another md block.
For example:
::pre .embedded I am so smart::md It is really amazing how smart I am. Behold my intelligence:
1. My IQ is over 9000. 2. I am really good looking. * This is an important point. * Wait, what does that have to do with intelligence? This is an internal heading::h Yeah, what about it? An internal block::md This is what I usually use instead as it mirrors how I think about the topic (subtopic is a subtree).
Turns into this:
::comment Formatted a bit for legibility, we avoid indenting to save on whitespace normally. ::div .embedded ::raw
I am so smart
It is really amazing how smart I am. Behold my intelligence:
- My IQ is over 9000.
- I am really good looking.
- This is an important point.
- Wait, what does that have to do with intelligence?
This is an internal heading
Yeah, what about it?
An internal block
This is what I usually use instead as it mirrors how I think about the topic (subtopic is a subtree).
Additionally we support tables. For example:
::js // I got lazy and didn't want to write it twice, so I just did this as // a script.
let text=` ::comment This is a comment by the way! It is not in the rendered html. The first row of the table is taken to be the headings for the table. There is no requirement to have the same number of cells in each row, but user beware, it gets wonky. The Nodes::table Node Type | Block Name | Heading MD | md | Yes DIV | div | Yes STRING | --- | --- PARA | --- | --- TITLE | title | Yes HEADING | h | Yes TABLE | table | Yes TABLE_ROW | --- | --- STYLESHEETS | css | --- LINKS | links | --- SCRIPTS | script | --- IMPORT | import | --- IMAGE | img | Yes BULLETS | --- | Yes RAW | raw | No PRE | pre | Yes LIST | --- | Yes LIST_ITEM | --- | No KEYVALUE | kv | Yes KEYVALUEPAIR | --- | No IMGLINKS | imglinks | Yes TOC | toc | Yes COMMENT | comment | --- CONTAINER | --- | No QUOTE | quote | Yes JS | js | No DETAILS | details | Yes INVALID | --- | --- ::md * Node Type is the type of the node. * Block name is how it is introduced via the double colon syntax (an empty entry indicates the node can only be created via scripts or implicitly as part of another node). * Heading is whether or not the header is turned into a heading. * The INVALID node will cause an error if encountered during rendering. It can be used as a poison node when debugging. For more detailed information, see the [reference](REFERENCE.html). ::links reference = REFERENCE.html ` let prenode = ctx.make_node(NodeType.PRE, {classes:['embedded'](embedded)}); for(let line of text.trim().split('\n')) prenode.add_child(line.trimRight()); node.parent.add_child(prenode) // parse is convenient, it appends the nodes by // parsing the string as if it were a document. node.parent.parse('::md\n And here is that table') node.parent.parse(text)
Self-Contained::md .dnd documents can include css and js files. They will be placed into the head of the document so that the html page is completely self-contained. However, you don't have to write them inline here in one document. You can include them in the document by the appropriate block.
Example:
::pre .embedded ::comment You haven't seen this before. The '#' symbol to the right of the double colon indicates a directive. Only certain directives are allowed. For example, this #import directive tells the system to not interpret the contents as raw strings to be included in a <script> tag, but instead as file paths to load.
css blocks also support #import with the same meaning, but for <style>. ::css #import cssfile1.css another/css/file.css and/another.css ::script #import somejsfile.js another/jsfile.js ::css * { box-sizing: border-box; }
Images can also be included. They are base64-encoded and stored as a data string in the html page. You can use the
#noinline
directive to disable this behavior.Attributes, Classes and Directives::md Blocks can have classes, which directly correspond to css classes in the output html.
Example:
::pre .embedded Hola::div .foo .bar hello, aloha In this example the Hola div will have
foo
andbar
as css classes.Blocks can also have attributes, which are user defined tags. They only have whatever meaning you give to them.
Example:
::pre .embedded A room::md @coord(1,2) some stuff is in the room Another room::md @coord(4, 6) A goblin is in this room.
A block can have any number of attributes. Attributes are identifiers and can have arguments in parens. The contents of the parens are stored as a string.
Javascript blocks can retrieve the attributes of a node via the .attributes field. It presents a map-like interface to the attributes. You can also set an attribute without a value, which will give it an empty string as its value. Many things only check for the presence of the key and ignore the value.
Directives::md Blocks can also have directives, which are prefixed by the '#'.
Example: ::pre .embedded Don't look::div #hide Don't put me in the document! Duplicate Heading::h #id(my-id) Duplicate Heading::h #id(my-id-2) Don't ID me bro::md #noid IDs are for squares! The following directives are currently used. ::table Attribute | Meaning `#noid` | Don't give the heading an id `#id(iden)` | Instead of the automatic id, use `iden` as the id for the heading `#hide` | Don't output the block in the rendered output. `#noinline` | Produce a link (href) instead of embedding. `#import` | Treat the lines inside the block as paths to be imported and import them as children of this node. Directives may be expanded in future versions.
But Wait, There's More::md The structured document format is convenient to write in, but sometimes you need to manipulate the document programmatically. Javascript blocks are your friend.
example:
::pre .embedded ::js
js blocks have 3 special variables in them. node: this node (the js block) ctx: this variable represents the state of compiling. It offers methods such as \
make_node` to create new nodes that can be inserted into the document. NodeType: This is actually a do-nothing object, that is used to namespace the types of the nodes. This is useful because you need to choose a type if you make a new node. You can also check the `type` attribute on nodes. ` for(let child of node.parent.children){ if(child.type == NodeType.PARA){ for(let line of child.children){ if(line.header.includes('example')) line.header = 'For Example:'; } } if(child.type == NodeType.PRE){ child.add_child('::js'); for(let line of node.children){ child.add_child(' '+line.header); } break; } } // If you're paying attention, you'll realize this js block added itself // to the document.Javascript blocks are isolated.
You can print things in javascript blocks, using
console.log
. I used it several times while writing this!::pre .embedded ::js
This block will print out every node in the document. The system can do this as well more efficiently, but this is just showing off that io works as expected.
function walk(n, depth){ if(depth > 10){ return; } console.log('--'.repeat(depth), n); for(let child of n.children){ walk(child, depth+1); } } walk(ctx.root, 0);Here is a fun demo. We will now embed the entire document via javascript. This is all done at compile time. You can even see the javascript block that was used to embed the text.
::js let details = ctx.make_node(NodeType.DETAILS, {header:'This Document'}); let prenode = ctx.make_node(NodeType.PRE, {classes:'embedded'}); //
add_child
can accept two kinds of arguments: nodes and strings // strings are converted to STRING nodes. for(let line of FileSystem.load_file(ctx.sourcepath).split('\n')) prenode.add_child(line); details.add_child(prenode); details.id = 'this-document'; ctx.root.add_child(details);::comment Normally I would put the css in its own file, but this README itself needs to be self-contained. ::css .embedded { border: 1px solid black; max-width: 44em; width: auto; padding: 0 1em; } div.container { max-width: 44em; grid-column: 2; grid-row:1; }
- { box-sizing: border-box; } a { text-decoration: none; color: currentcolor; border-bottom: 1px grey dotted; } div.root { display: grid; grid-template-columns: 15em auto; grid-column-gap: 4em; padding-bottom: 90vh; } nav a { border-bottom: 0; text-decoration: none; } nav li { list-style-type: square; } nav { position: fixed; } th, td { padding: 4px 8px; border: 1px solid grey; text-align: left; } th { border-bottom: 2px solid black; } table { border-collapse: collapse; margin:auto; } body { font-family: "Helvetica", "Verdana", "Tahoma", sans; } code, pre { font-family: "SF Mono", ui-mono, "Cascadia Mono", Consolas, monospace; } pre { font-size: 12px; }
@media only screen and (max-width: 720px) { nav { display: none; } div.root { display: initial; } } code { background-color: #f3f3f3; padding: 1px; padding-left: 3px; padding-right: 3px; }
::js // this shows more raw manipulation of the tree. // we actually temporarily detach the root node from the context let root = ctx.root; root.type = NodeType.DIV; root.classes.add('container'); let new_root = ctx.make_node(NodeType.DIV, {classes:'root'}); root.detach(); new_root.add_child(root); // TOC blocks are kind of special. As one of the last things, the system // will walk the document tree and create a toc of all the h2s and h3s. new_root.add_child(ctx.make_node(NodeType.TOC)); ctx.root = new_root;
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Hashes for pydndc-1.5.0-cp312-cp312-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 8e8f273c022f8e0e0d9be064497229f94dae4d0a4179c3aac7895ac067a81123 |
|
MD5 | 6e5dd559f3ff77d43925eb4bee5befda |
|
BLAKE2b-256 | 4f3dd3704d2aaaf7d6799948efc4c8b540ba48a52579a79bb65fb9b9768d397d |
Hashes for pydndc-1.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 3450b6d1d4e3bdd68938df5479895fe9912be5b9c7595f68ca324e48be9238a6 |
|
MD5 | 71f6a50d630a107ba97389e991db4ffa |
|
BLAKE2b-256 | 0f5acfa74bc2520c2413bc52dade1761fdc12b584494c59a6fb6e48a9d3a84d3 |
Hashes for pydndc-1.5.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 568801307eb8cc11664f4402340c0173af90d5ee7522016e9d163432a7364b1c |
|
MD5 | 18b6f0b52d11f8cb2d272480439bd05b |
|
BLAKE2b-256 | 844970f05c46d8acabaedafe6a7ba018f39f8bd8ff4c7fb4c3a5cbbfc9288666 |
Hashes for pydndc-1.5.0-cp312-cp312-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | cde597a76f2505091e2a9ce45e35e83e91345e3a33f2013202c0234f706c933f |
|
MD5 | 7c7bd28d7431ddf030789e58826c32a7 |
|
BLAKE2b-256 | 694eebdaf80fc40e65a32675942d19ce9a4f9552bf588b5ff67c472aa3e609c5 |
Hashes for pydndc-1.5.0-cp312-cp312-macosx_10_9_universal2.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6a16e999c732347c18c5482d83646c2ca2434524dc386944f172f78ad5b92724 |
|
MD5 | 8636ba3fa2a671a929bbfda59d631d55 |
|
BLAKE2b-256 | 6d11fc8d21dc2d86aecf7bb343fac04d0175d4efa4bcbdc9eb6df82521b2732d |
Hashes for pydndc-1.5.0-cp311-cp311-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 67897783e651ac88158befcb5649e86636a50563fed01d982b63950981fbbfb0 |
|
MD5 | 5df8f96f8f1b5c5591983d141a758ca2 |
|
BLAKE2b-256 | 642472228448d43a81f67da187158b4322b70e3d36facee6332d836b3c26d4bd |
Hashes for pydndc-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | d952e8e4c004f0480641d1cd3d70af67bdb3eb4b7772a8b5acfb136efa50d1f3 |
|
MD5 | b776f3b9a6f6694b9bedc04b404a239e |
|
BLAKE2b-256 | e9fa97d2292eded44d07e0c3015c09339abff0097d3ea19a4456bea6d2efff86 |
Hashes for pydndc-1.5.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 9fe783c1b764cd5256f007e397b25ee227d3ea8fb1defb79579ba4ca84324f77 |
|
MD5 | 62b4a5d6c27dddd1ada28b79b0a01862 |
|
BLAKE2b-256 | 8eb5423eeb43f0829e0ce016192bd2cdb3309093b3a2f780ba8b676ab78b97bb |
Hashes for pydndc-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | a3efb6ffe3ee4ef225ed558576a96a1a588d56c87d260d52b1460bc644de30b2 |
|
MD5 | 5fb0566c946be5d553fd1088f9cebf3f |
|
BLAKE2b-256 | ab347f801da27fc3203482d8c26aee9d72265e84762ad057c739c2b94ecd8777 |
Hashes for pydndc-1.5.0-cp311-cp311-macosx_10_9_universal2.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | a246b6c638bde3448a95e4f7b3139d52c7f42aa5027610eb8df54bedde6c717f |
|
MD5 | 3c0fd10ea5fa3fdfae4205ea060c302f |
|
BLAKE2b-256 | 8944347bb5a227d30913db367dafa898bf7d62377d763824e673a86648ee8d76 |
Hashes for pydndc-1.5.0-cp310-cp310-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2361212fbc103d922cf4c2a424e8ef4ab0d0ec96adbf92c2561dbb1e4063ec7e |
|
MD5 | a9c9a8202476a8332990058fd450d6a4 |
|
BLAKE2b-256 | 1210281e674a24e7761323cbdebc7d46de23d25a265803a03d0990af5ed31123 |
Hashes for pydndc-1.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2de279101a274ef28f7cce29d431da61f29a45679706e3461c50c5bdc5c0c65b |
|
MD5 | fd112c227a1a7637893dd46d2bca4827 |
|
BLAKE2b-256 | 9cc17c24d35a08734a46f55327cf7d4f74427e18906c92c0cd754d05955bc5d7 |
Hashes for pydndc-1.5.0-cp310-cp310-macosx_11_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 9f2c5bc1459922100550bc529ff326533f4af54e4918a472fc9bfe6e01f9d15f |
|
MD5 | 875ab3e88c8944f5d8c4080cefa2e688 |
|
BLAKE2b-256 | 38d8dd57df921be7ef771da5400e1d1ee9b6ed11c49e2d80725dec030d086ca8 |
Hashes for pydndc-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 40adedf1394296211ec0d761612fd623010adc02ea9d206f974784497db5d323 |
|
MD5 | cdb4deffbc2d6539f3ce84d5bf7944cd |
|
BLAKE2b-256 | 0fceaaf822ecbd3c16aff1a79683cf90e5be38e5a8548ab783ccd65fee9791d0 |
Hashes for pydndc-1.5.0-cp310-cp310-macosx_10_9_universal2.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1c758620063a30920a9da9e307b1ed09503f8e62a3d86646b252970b73f163ee |
|
MD5 | 175f2979bf3ae974ad499994e192e4f2 |
|
BLAKE2b-256 | 5534322843bed19f3074f83fbb959ed9e39c4e050bcf17d43b1a1fcabd70382a |
Hashes for pydndc-1.5.0-cp39-cp39-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | ad34a8e95204aac3e4f0e1d028b11969b8cf7bf3a41f98ef1e8cb0282734e254 |
|
MD5 | c1e5d5d373092850ff5293fa819e4ed0 |
|
BLAKE2b-256 | 4282c29a3b93f44f9ccff92673922d141d72f1edd60646650833cdf3cbb26d72 |
Hashes for pydndc-1.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 4acd150799904c450874202a7fe8f2fcdafd504977b49ce490292c6281abec1d |
|
MD5 | 5a586d46c5ab9e20e620927a82570d66 |
|
BLAKE2b-256 | 7d5d0605171c41f24780b43d4fea769dda28aa68705bca857bd38e73fa48b82d |
Hashes for pydndc-1.5.0-cp39-cp39-macosx_11_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6bf9c3faeb779e40ed747a632adbb496443658717c521773207e06ea55cb916a |
|
MD5 | 674a458f3cbc026d0e54b2770733e94c |
|
BLAKE2b-256 | 2935f9c4d06a48f16ddafe118a7e5ba65655edc283ea2331e0df0cd0803c90a3 |
Hashes for pydndc-1.5.0-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 9e5b3f9938de866146e8b5854c7ae6774560c16d71527fcfa95aa5a591726af9 |
|
MD5 | 5656134e0dde88ded9b02f072c83bd17 |
|
BLAKE2b-256 | 2f7a3fca65e9c76c404d31fbf0de8fe6656994f5e0bb0684b77be55f61aa4427 |
Hashes for pydndc-1.5.0-cp39-cp39-macosx_10_9_universal2.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 0b1c58dc470a8e124c865b76067c4927a6196ae7d77505ab2d4588a4bc076eab |
|
MD5 | d7f6f6a4a8d3708f5c02bccb5111c482 |
|
BLAKE2b-256 | 50981da26db3f4cc335d1f4ee4327979bb0954911c78dfa3f42ed6f90fa4c966 |
Hashes for pydndc-1.5.0-cp38-cp38-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | e676ec6790c9db9396407475b2183affcb387906bff514676631921295685cb1 |
|
MD5 | 4f1e716a97436bfa5e599d0e719a7721 |
|
BLAKE2b-256 | c5bd2f35b5c5e46c6a0288e7352de653ba2ba4a631156ccbb04b5d8c02960cc7 |
Hashes for pydndc-1.5.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | c2f436ca9d56daed0a874719add8975e5713b60544122c2647e039a1815a24e6 |
|
MD5 | 7103fda9ff46898d1597d88a4d44f6aa |
|
BLAKE2b-256 | 910ac8774b16418fd30fc7b9b3f5a02b770c60031269b94352746ec6be73097a |
Hashes for pydndc-1.5.0-cp38-cp38-macosx_11_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | ec66caf7c90ab9fc95682088205b2bbfbaf9220cd70a5e72be07bc3eb547b5d8 |
|
MD5 | d37165a9b3bb5f080d1db0d75b7e4fdc |
|
BLAKE2b-256 | 874d2110a2ee61c97e2493a60d871f1f1d3f61df40d5ec34427bd0d4aee4391c |
Hashes for pydndc-1.5.0-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | d15680d280c33c3b58644e6366dd146c049a1fad8569c7cec9d8a488c1133238 |
|
MD5 | 9cadeaee6b38927e6754b8ca570f1b84 |
|
BLAKE2b-256 | 2d373a142f9c54b69986d8712065bac5fe7a668e4b1d111ec0f2831497c3d81e |
Hashes for pydndc-1.5.0-cp38-cp38-macosx_10_9_universal2.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | f573cf4bd254f9e11299b509ecc23801ec987965fa259d33fccfe5d6842ad90d |
|
MD5 | bc71838f471c43315b044b867b6a7ac0 |
|
BLAKE2b-256 | 96195427f1538e515d862ac22554ca690655df3a597cbdcf63da992141c6b6e2 |
Hashes for pydndc-1.5.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2b29817c26a3c70e4930f6bd9e78f6c30116d85eb98ae0c7e928ce472423a627 |
|
MD5 | 9e420ee4a3054b51230661df8b4bfa71 |
|
BLAKE2b-256 | a9c662a84d420b608cf93dd69ba6c1d5426e41111ac5746ee8a3fc020ae82e8f |
Hashes for pydndc-1.5.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | f6b85f6461e544a344a62bd902ad54e7d605aaaedfcb861994a6b7ad4b7edada |
|
MD5 | f8c6c8e84c3f4e3a4898255bfe1cce28 |
|
BLAKE2b-256 | 926e9d6539926b0c3acd54b45c46424896b0d82ac83f05670ad997aa7cfff661 |