Docs: add error documentation generation
This commit is contained in:
parent
19eb1c2520
commit
385a600e98
3
.gitignore
vendored
3
.gitignore
vendored
@ -21,6 +21,8 @@ __pycache__
|
|||||||
/scripts/opam-test-all.sh.DONE
|
/scripts/opam-test-all.sh.DONE
|
||||||
|
|
||||||
/docs/introduction/readme.rst
|
/docs/introduction/readme.rst
|
||||||
|
/docs/api/errors.rst
|
||||||
|
/docs/_extensions/*.pyc
|
||||||
|
|
||||||
*.install
|
*.install
|
||||||
.merlin
|
.merlin
|
||||||
@ -30,4 +32,3 @@ __pycache__
|
|||||||
|
|
||||||
*.rej
|
*.rej
|
||||||
*.orig
|
*.orig
|
||||||
|
|
||||||
|
@ -5,18 +5,25 @@ SPHINXPROJ = Tezos
|
|||||||
SOURCEDIR = .
|
SOURCEDIR = .
|
||||||
BUILDDIR = _build
|
BUILDDIR = _build
|
||||||
|
|
||||||
|
DOCGENDIR = doc_gen
|
||||||
|
DOCERRORDIR = $(DOCGENDIR)/errors
|
||||||
|
|
||||||
all: html linkcheck
|
all: html linkcheck
|
||||||
|
|
||||||
linkcheck:
|
linkcheck:
|
||||||
$(SPHINXBUILD) -b linkcheck "$(SOURCEDIR)" "$(BUILDDIR)"
|
$(SPHINXBUILD) -b linkcheck "$(SOURCEDIR)" "$(BUILDDIR)"
|
||||||
|
|
||||||
|
api/errors.rst: $(DOCERRORDIR)/error_doc.ml
|
||||||
|
@jbuilder build $(DOCERRORDIR)/error_doc.exe
|
||||||
|
../_build/default/docs/$(DOCERRORDIR)/error_doc.exe > api/errors.rst
|
||||||
|
|
||||||
.PHONY: help Makefile
|
.PHONY: help Makefile
|
||||||
|
|
||||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||||
html: Makefile
|
html: Makefile api/errors.rst
|
||||||
@$(SPHINXBUILD) -b html "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS)
|
@$(SPHINXBUILD) -b html "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@-rm -Rf "$(BUILDDIR)"
|
@-rm -Rf "$(BUILDDIR)"
|
||||||
@-rm -Rf introduction/readme.rst
|
@-rm -Rf introduction/readme.rst api/errors.rst
|
||||||
|
204
docs/doc_gen/errors/error_doc.ml
Normal file
204
docs/doc_gen/errors/error_doc.ml
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
(**************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Copyright (c) 2014 - 2018. *)
|
||||||
|
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||||
|
(* *)
|
||||||
|
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||||
|
(* *)
|
||||||
|
(**************************************************************************)
|
||||||
|
|
||||||
|
(* Todo : add section descriptions *)
|
||||||
|
|
||||||
|
let default_section_id = "default"
|
||||||
|
let default_section_title = "Miscellaneous"
|
||||||
|
|
||||||
|
(* Association list where keys are set of identifier's prefixes that
|
||||||
|
maps to a section title. The ordering of sections in the rst output
|
||||||
|
depends on their position in this list.
|
||||||
|
|
||||||
|
e.g. : an error which id is 'utils.Timeout' will be documented
|
||||||
|
under the `Miscellaneous` section which will be displayed at the
|
||||||
|
bottom of the document. Unprefixed ids or unreferenced prefixes
|
||||||
|
will default to `Miscellaneous` *)
|
||||||
|
let section_titles =
|
||||||
|
[
|
||||||
|
[ "proto" ], "Protocol Alpha";
|
||||||
|
[ "baking" ], "Baking" ;
|
||||||
|
[ "contract" ], "Smart Contracts" ;
|
||||||
|
[ "distributed_db" ], "Database" ;
|
||||||
|
[ "micheline" ; "michelson" ], "Smart Contracts" ;
|
||||||
|
(* [ "michelson" ], "Michelson" ; *)
|
||||||
|
[ "node" ], "Client Node" ;
|
||||||
|
[ "operation" ], "Operations" ;
|
||||||
|
[ "prevalidation" ], "Prevalidation" ;
|
||||||
|
[ "raw_store" ], "Store" ;
|
||||||
|
[ "rpc_client" ], "RPC Client" ;
|
||||||
|
[ "tez" ], "Tezos operations" ;
|
||||||
|
[ "validator" ], "Validator" ;
|
||||||
|
[ "worker" ], "Worker" ;
|
||||||
|
(* [ "cli" ], "Command Line" ; *)
|
||||||
|
[ "cli"; "utils"; default_section_id ], default_section_title ;
|
||||||
|
]
|
||||||
|
|
||||||
|
let categories_detail =
|
||||||
|
[ "temporary", "An error resulting from an operation that might be \
|
||||||
|
valid in the future, for example, a contract’s balance \
|
||||||
|
being too low to execute the intended operation. This \
|
||||||
|
can be fixed by adding more to the contract’s balance."
|
||||||
|
; "branch", "An error that occurs in one branch of the chain, but may not \
|
||||||
|
occur in a different one. For example, receiving an \
|
||||||
|
operation for an old or future protocol version."
|
||||||
|
; "permanent", "An error that is not recoverable because the operation \
|
||||||
|
is never going to be valid. For example, an invalid ꜩ \
|
||||||
|
notation." ]
|
||||||
|
|
||||||
|
let pp_rst_title ~char ppf title =
|
||||||
|
let sub = String.map (fun _ -> char) title in
|
||||||
|
Format.fprintf ppf "@[<v 0>%s@\n@]@[<v 0>%s@\n@\n@]" title sub
|
||||||
|
|
||||||
|
let pp_rst_h1 = pp_rst_title ~char:'#'
|
||||||
|
let pp_rst_h2 = pp_rst_title ~char:'*'
|
||||||
|
let pp_rst_h3 = pp_rst_title ~char:'='
|
||||||
|
let pp_rst_h4 = pp_rst_title ~char:'`'
|
||||||
|
|
||||||
|
let string_of_err_category =
|
||||||
|
let open Error_monad in function
|
||||||
|
| `Branch -> "branch"
|
||||||
|
| `Temporary -> "temporary"
|
||||||
|
| `Permanent -> "permanent"
|
||||||
|
|
||||||
|
let pp_info_to_rst
|
||||||
|
ppf
|
||||||
|
{ Error_monad.id ; title ; category ; description ; schema } =
|
||||||
|
let open Format in
|
||||||
|
|
||||||
|
fprintf ppf "@[<v 2>- **%s**@,@,"
|
||||||
|
(if title = "" then "<Untitled>" else title) ;
|
||||||
|
|
||||||
|
fprintf ppf "@[<v 0>%s@\n@\n@]"
|
||||||
|
(if description = "" then "Not description available" else description) ;
|
||||||
|
|
||||||
|
fprintf ppf "@[<v 0>* *Id* : %s@\n@\n@]" id ;
|
||||||
|
|
||||||
|
fprintf ppf "@[* *Category* : %s@\n@\n@]" (string_of_err_category category) ;
|
||||||
|
|
||||||
|
fprintf ppf "@[<v 2>.. container:: schema-button@\n@\n" ;
|
||||||
|
fprintf ppf "@[<v 2>Show schema@]@]@\n@\n" ;
|
||||||
|
|
||||||
|
fprintf ppf "@[<v 2>.. container:: schema@\n@\n" ;
|
||||||
|
fprintf ppf "@[<v 2>.. code-block:: json@\n@\n" ;
|
||||||
|
|
||||||
|
fprintf ppf "@[%a@]@]@]@]" Json_schema.pp schema
|
||||||
|
|
||||||
|
module ErrorSet = Set.Make(struct
|
||||||
|
type t = Error_monad.error_info
|
||||||
|
let compare { Error_monad.id ; _ } { Error_monad.id = id' ; _ } =
|
||||||
|
String.compare id id'
|
||||||
|
end)
|
||||||
|
|
||||||
|
module ErrorPartition = struct
|
||||||
|
include Map.Make(struct
|
||||||
|
include String
|
||||||
|
let titles = List.map snd section_titles
|
||||||
|
|
||||||
|
let compare s s' =
|
||||||
|
let idx s =
|
||||||
|
let rec loop acc = function
|
||||||
|
| [] -> assert false
|
||||||
|
| h::_ when h = s -> acc
|
||||||
|
| _::t -> loop (acc + 1) t
|
||||||
|
in loop 0 titles
|
||||||
|
in
|
||||||
|
Pervasives.compare (idx s) (idx s')
|
||||||
|
end)
|
||||||
|
|
||||||
|
let add_error (id : key) (error : Error_monad.error_info) (map : 'a t) =
|
||||||
|
let lr_opt = Stringext.cut id ~on:"." in
|
||||||
|
|
||||||
|
let id_prefix =
|
||||||
|
match lr_opt with
|
||||||
|
| None -> default_section_id
|
||||||
|
| Some (prefix, _r) -> prefix
|
||||||
|
in
|
||||||
|
|
||||||
|
let title =
|
||||||
|
try
|
||||||
|
snd (List.find
|
||||||
|
(fun (id_set, _) -> List.mem id_prefix id_set)
|
||||||
|
section_titles)
|
||||||
|
with
|
||||||
|
| Not_found -> default_section_title
|
||||||
|
in
|
||||||
|
|
||||||
|
let set =
|
||||||
|
try
|
||||||
|
find title map
|
||||||
|
with
|
||||||
|
| Not_found -> ErrorSet.empty
|
||||||
|
in
|
||||||
|
|
||||||
|
add title (ErrorSet.add error set) map
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
let pp_error_map ppf (map : ErrorSet.t ErrorPartition.t) : unit =
|
||||||
|
let open Format in
|
||||||
|
ErrorPartition.iter (fun section_title set ->
|
||||||
|
fprintf ppf "%a" pp_rst_h2 section_title ;
|
||||||
|
|
||||||
|
ErrorSet.iter
|
||||||
|
(fun error_repr ->
|
||||||
|
fprintf ppf "@[%a@]@\n@\n" pp_info_to_rst error_repr
|
||||||
|
) set
|
||||||
|
) map
|
||||||
|
|
||||||
|
let print_script ppf =
|
||||||
|
(* HACK : show/hide JSON schemas + style *)
|
||||||
|
Format.fprintf ppf "@[<v 2>.. raw:: html@\n@\n" ;
|
||||||
|
Format.fprintf ppf "@[<v 0>%s%s@]@\n@\n@]"
|
||||||
|
"<script>document.addEventListener('DOMContentLoaded', function(){\
|
||||||
|
$(\".schema-button\").click(function(){$(this).next(\".schema\")\
|
||||||
|
.first().toggle()})}, false);</script>"
|
||||||
|
"<style>.schema { display:none; margin:0 0 0 10px; }\
|
||||||
|
.schema-button { cursor:pointer; font-size:11px;\
|
||||||
|
font-weight: bold; background-color: #EEEEEE;\
|
||||||
|
color: #333333; padding: 2px 6px 2px 6px;\
|
||||||
|
border-top: 1px solid #CCCCCC; border-right: 1px solid #333333;\
|
||||||
|
border-bottom: 1px solid #333333; border-left: 1px solid #CCCCCC;\
|
||||||
|
width : -moz-fit-content; }\
|
||||||
|
section li { margin:10px 0 10px 0; } </style>"
|
||||||
|
|
||||||
|
(* Main *)
|
||||||
|
let () =
|
||||||
|
let open Format in
|
||||||
|
let ppf = std_formatter in
|
||||||
|
|
||||||
|
(* Header *)
|
||||||
|
let title = "Tezos Client Errors" in
|
||||||
|
fprintf ppf "%a" pp_rst_h1 title ;
|
||||||
|
|
||||||
|
print_script ppf ;
|
||||||
|
|
||||||
|
fprintf ppf "This document references possible errors.@\n@\n" ;
|
||||||
|
|
||||||
|
fprintf ppf "There are three categories of error :@\n@\n" ;
|
||||||
|
|
||||||
|
List.iter (fun (cat, descr) ->
|
||||||
|
fprintf ppf "- :literal:`%s` - %s@\n@\n" cat descr) categories_detail ;
|
||||||
|
|
||||||
|
fprintf ppf "See `The Error Monad`_ for further details.@\n@\n" ;
|
||||||
|
fprintf
|
||||||
|
ppf ".. _The Error Monad: \
|
||||||
|
../tutorials/error_monad.html#the-actual-tezos-error-monad@\n@\n" ;
|
||||||
|
|
||||||
|
(* Body *)
|
||||||
|
let map =
|
||||||
|
let all_errors =
|
||||||
|
Error_monad.get_registered_errors () in
|
||||||
|
List.fold_left
|
||||||
|
(fun acc ( Error_monad.{ id ; _ } as error ) ->
|
||||||
|
ErrorPartition.add_error id error acc
|
||||||
|
) ErrorPartition.empty all_errors
|
||||||
|
in
|
||||||
|
|
||||||
|
fprintf ppf "%a" pp_error_map map
|
20
docs/doc_gen/errors/jbuild
Normal file
20
docs/doc_gen/errors/jbuild
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
(jbuild_version 1)
|
||||||
|
|
||||||
|
(executable
|
||||||
|
((name error_doc)
|
||||||
|
(libraries
|
||||||
|
(tezos-shell
|
||||||
|
tezos-embedded-protocol-alpha))
|
||||||
|
(flags (:standard -w -9+27-30-32-40@8
|
||||||
|
-open Tezos_base
|
||||||
|
-open Tezos_error_monad
|
||||||
|
-open Tezos_data_encoding
|
||||||
|
-open Tezos_embedded_protocol_alpha
|
||||||
|
-open Tezos_embedded_protocol_environment_alpha
|
||||||
|
-safe-string
|
||||||
|
-linkall))))
|
||||||
|
|
||||||
|
(alias
|
||||||
|
((name runtest_indent)
|
||||||
|
(deps ((glob_files *.ml*)))
|
||||||
|
(action (run bash ${libexec:tezos-stdlib:test-ocp-indent.sh} ${^}))))
|
@ -83,6 +83,7 @@ license when the main network lunches.
|
|||||||
README
|
README
|
||||||
api/api-inline
|
api/api-inline
|
||||||
api/cli-commands
|
api/cli-commands
|
||||||
|
api/errors
|
||||||
|
|
||||||
Indices and tables
|
Indices and tables
|
||||||
==================
|
==================
|
||||||
|
@ -19,6 +19,8 @@ type error += Cannot_freeze_endorsement_deposit (* `Permanent *)
|
|||||||
type error += Inconsistent_endorsement of public_key_hash list (* `Permanent *)
|
type error += Inconsistent_endorsement of public_key_hash list (* `Permanent *)
|
||||||
type error += Empty_endorsement
|
type error += Empty_endorsement
|
||||||
type error += Invalid_block_signature of Block_hash.t * Ed25519.Public_key_hash.t (* `Permanent *)
|
type error += Invalid_block_signature of Block_hash.t * Ed25519.Public_key_hash.t (* `Permanent *)
|
||||||
|
type error += Invalid_signature (* `Permanent *)
|
||||||
|
type error += Invalid_stamp (* `Permanent *)
|
||||||
|
|
||||||
let () =
|
let () =
|
||||||
register_error_kind
|
register_error_kind
|
||||||
@ -108,7 +110,9 @@ let () =
|
|||||||
(req "block" Block_hash.encoding)
|
(req "block" Block_hash.encoding)
|
||||||
(req "expected" Ed25519.Public_key_hash.encoding))
|
(req "expected" Ed25519.Public_key_hash.encoding))
|
||||||
(function Invalid_block_signature (block, pkh) -> Some (block, pkh) | _ -> None)
|
(function Invalid_block_signature (block, pkh) -> Some (block, pkh) | _ -> None)
|
||||||
(fun (block, pkh) -> Invalid_block_signature (block, pkh))
|
(fun (block, pkh) -> Invalid_block_signature (block, pkh));
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
~id:"baking.invalid_signature"
|
~id:"baking.invalid_signature"
|
||||||
~title:"Invalid block signature"
|
~title:"Invalid block signature"
|
||||||
~description:"The block's signature is invalid"
|
~description:"The block's signature is invalid"
|
||||||
@ -251,9 +255,6 @@ let check_header_hash header stamp_threshold =
|
|||||||
let hash = Block_header.hash header in
|
let hash = Block_header.hash header in
|
||||||
check_hash hash stamp_threshold
|
check_hash hash stamp_threshold
|
||||||
|
|
||||||
type error +=
|
|
||||||
| Invalid_stamp
|
|
||||||
|
|
||||||
let check_proof_of_work_stamp ctxt block =
|
let check_proof_of_work_stamp ctxt block =
|
||||||
let proof_of_work_threshold = Constants.proof_of_work_threshold ctxt in
|
let proof_of_work_threshold = Constants.proof_of_work_threshold ctxt in
|
||||||
if check_header_hash block proof_of_work_threshold then
|
if check_header_hash block proof_of_work_threshold then
|
||||||
|
Loading…
Reference in New Issue
Block a user