From 66599fda2532a032d610c040e95c8c4a5cd16cd4 Mon Sep 17 00:00:00 2001 From: Ara Adkins Date: Tue, 4 May 2021 09:49:53 +0100 Subject: [PATCH] Enhance examples for `Standard.Base.*` (#1714) --- .gitignore | 7 + .../Standard/src/Base/Error/Common.enso | 1 + .../Standard/src/Base/Error/Extensions.enso | 46 +- .../std-lib/Standard/src/Base/Math.enso | 4 + .../Standard/src/Base/Meta/Enso_Project.enso | 2 + .../Standard/src/Base/Network/Http.enso | 394 +++++++--- .../Standard/src/Base/Network/Http/Form.enso | 99 ++- .../src/Base/Network/Http/Header.enso | 272 ++++--- .../src/Base/Network/Http/Request.enso | 78 +- .../src/Base/Network/Http/Response.enso | 33 + .../src/Base/Network/Http/Response/Body.enso | 25 + .../Standard/src/Base/Network/Proxy.enso | 5 +- .../Standard/src/Base/Network/Uri.enso | 126 ++-- .../Standard/src/Base/System/Environment.enso | 8 +- .../Standard/src/Base/System/File.enso | 673 ++++++++++++------ .../Standard/src/Base/System/Platform.enso | 5 +- .../Standard/src/Base/System/Process.enso | 69 +- .../src/Base/System/Process/Exit_Code.enso | 10 +- .../std-lib/Standard/src/Examples.enso | 64 ++ .../runtime/src/main/resources/Builtins.enso | 108 ++- test/Tests/src/Network/Http_Spec.enso | 24 + test/Tests/src/System/Process_Spec.enso | 18 +- 22 files changed, 1492 insertions(+), 579 deletions(-) diff --git a/.gitignore b/.gitignore index fc645d70161..682eb3d8ee5 100644 --- a/.gitignore +++ b/.gitignore @@ -105,3 +105,10 @@ project/metals.sbt ################# build-cache/ + +################### +## Enso-Specific ## +################### + +distribution/std-lib/Standard/data/scratch_file + diff --git a/distribution/std-lib/Standard/src/Base/Error/Common.enso b/distribution/std-lib/Standard/src/Base/Error/Common.enso index 99622f34cdf..ca0dbfcea1c 100644 --- a/distribution/std-lib/Standard/src/Base/Error/Common.enso +++ b/distribution/std-lib/Standard/src/Base/Error/Common.enso @@ -1,6 +1,7 @@ from Standard.Base import all type Illegal_State_Error + ## UNSTABLE A generic error that indicates that a given operation cannot be performed diff --git a/distribution/std-lib/Standard/src/Base/Error/Extensions.enso b/distribution/std-lib/Standard/src/Base/Error/Extensions.enso index 37461841dff..259f39f1aad 100644 --- a/distribution/std-lib/Standard/src/Base/Error/Extensions.enso +++ b/distribution/std-lib/Standard/src/Base/Error/Extensions.enso @@ -4,6 +4,15 @@ from Standard.Base import all UNSTABLE Returns the method name of the method that could not be found. + + > Example + Getting the method name from a no such method error. + + import Standard.Examples + + example_method_name = + error = Examples.no_such_method + error.method_name No_Such_Method_Error.method_name : Text No_Such_Method_Error.method_name = Meta.meta this.symbol . name @@ -22,11 +31,20 @@ type Unimplemented_Error message Unimplemented_Error.to_display_text : Text Unimplemented_Error.to_display_text = "An implementation is missing: " + this.message -## A function that can be used to indicate that something hasn't been +## ADVANCED + + A function that can be used to indicate that something hasn't been implemented yet. Arguments: - message: A description of what implementation is missing. + + > Example + Throwing an error to show that something is unimplemented. + + import Standard.Base.Error.Extensions + + example_unimplemented = Extensions.unimplemented unimplemented : Text -> Void unimplemented message="" = Panic.throw (Unimplemented_Error message) @@ -39,7 +57,11 @@ unimplemented message="" = Panic.throw (Unimplemented_Error message) > Example Catching an erroneous value and getting the length of its message. - (Time.Time_Error "Message").catch (err -> err.error_message.length) + + import Standard.Examples + + example_catch = + Examples.throw_error.catch (err -> err.message.length) Error.catch : (Error -> Any) -> Any Error.catch (handler = x->x) = this.catch_primitive handler @@ -49,7 +71,10 @@ Error.catch (handler = x->x) = this.catch_primitive handler > Example Displaying a dataflow error. - (Error.throw "oops!").to_default_visualization_data + + import Standard.Examples + + example_display = Examples.throw_error.to_default_visualization_data Error.to_default_visualization_data : Text Error.to_default_visualization_data = this.catch .to_default_visualization_data @@ -68,8 +93,13 @@ Error.to_display_text = "Error: " + (this.catch .to_display_text) is an error, the error is transformed using the provided function > Example - Wrapping an error value. - map.get "x" . map_error (_ -> ElementNotFound "x") + Transforming an error value. + + import Standard.Examples + + example_map_error = + map = Examples.map + map.get 10 . map_error (_ -> "The element 10 was not found.") Error.map_error : (Error -> Error) -> Any Error.map_error f = this.catch (x -> Error.throw (f x)) @@ -77,6 +107,7 @@ Error.map_error f = this.catch (x -> Error.throw (f x)) > Example Checking if the value 1 is an error. + 1.is_error Error.is_error : Boolean Error.is_error = True @@ -89,7 +120,10 @@ Error.is_error = True > Example Rethrowing a dataflow error as a panic. - Panic.rethrow (Error.throw "Oh, no!") + + import Standard.Examples + + example_rethrow = Panic.rethrow Examples.throw_error Panic.rethrow : (Any ! Any) -> Any Panic.rethrow value = value.catch Panic.throw diff --git a/distribution/std-lib/Standard/src/Base/Math.enso b/distribution/std-lib/Standard/src/Base/Math.enso index 248cd8b9b9d..499981a2ce1 100644 --- a/distribution/std-lib/Standard/src/Base/Math.enso +++ b/distribution/std-lib/Standard/src/Base/Math.enso @@ -5,6 +5,7 @@ from Standard.Base import all > Example Calculating the area of a circle. + circle_area r = 2 * Math.pi * r^2 pi : Decimal pi = 3.1415926535897932385 @@ -13,6 +14,7 @@ pi = 3.1415926535897932385 > Example Calculating the natural logarithm of 3. + 3.log Math.e e : Decimal e = 2.718281828459045235360 @@ -30,6 +32,7 @@ e = 2.718281828459045235360 > Example Calculate the smallest number out of 1 and 2. + Math.min 1 2 min : Number -> Number -> Number min a b = if a <= b then a else b @@ -47,6 +50,7 @@ min a b = if a <= b then a else b > Example Calculate the largest number out of 1 and 2. + Math.max 1 2 max : Number -> Number -> Number max a b = if a < b then b else a diff --git a/distribution/std-lib/Standard/src/Base/Meta/Enso_Project.enso b/distribution/std-lib/Standard/src/Base/Meta/Enso_Project.enso index 29844e3c9a4..99fd919a9f5 100644 --- a/distribution/std-lib/Standard/src/Base/Meta/Enso_Project.enso +++ b/distribution/std-lib/Standard/src/Base/Meta/Enso_Project.enso @@ -6,6 +6,7 @@ import Builtins > Example Get the root directory of the current project. + Enso_Project.root Builtins.Project_Description.root : File.File Builtins.Project_Description.root = File.File this.prim_root_file @@ -14,6 +15,7 @@ Builtins.Project_Description.root = File.File this.prim_root_file > Example Get the data directory of the current project. + Enso_Project.data Builtins.Project_Description.data : File.File Builtins.Project_Description.data = this.root / "data" diff --git a/distribution/std-lib/Standard/src/Base/Network/Http.enso b/distribution/std-lib/Standard/src/Base/Network/Http.enso index 3ad32aca0d7..1c76cd64ec5 100644 --- a/distribution/std-lib/Standard/src/Base/Network/Http.enso +++ b/distribution/std-lib/Standard/src/Base/Network/Http.enso @@ -24,20 +24,6 @@ polyglot java import java.net.URI polyglot java import java.time.Duration as Java_Duration polyglot java import org.enso.base.Http_Utils -## UNSTABLE - - An error when sending an Http request. - - Arguments: - - message: The message for the error. -type Request_Error message - -## UNSTABLE - - Convert a request error to a human-readable form. -Request_Error.to_display_text = - "Error when sending request: " + this.message - ## Create a new instance of the HTTP client. Arguments: @@ -56,7 +42,13 @@ Request_Error.to_display_text = > Example Create an HTTP client with extended timeout and proxy settings. - Http.new (timeout = 30.seconds) (proxy = Proxy.new "example.com" 8080) + + import Standard.Base.Data.Time.Duration + import Standard.Base.Network.Http + import Standard.Base.Network.Proxy + + example_new = + Http.new (timeout = 30.seconds) (proxy = Proxy.new "example.com" 8080) new : Duration -> Boolean -> Proxy -> Http new (timeout = 10.seconds) (follow_redirects = True) (proxy = Proxy.System) (version = Version.Http_1_1) = Http timeout follow_redirects proxy version @@ -68,8 +60,11 @@ new (timeout = 10.seconds) (follow_redirects = True) (proxy = Proxy.System) (ver - headers: Any headers for the options request. > Example - Send an Options request. - Http.options "http://httpbin.org" + Send an Options request. NOTE: This example will make a network request. + + import Standard.Base.Network.Http + + example_options = Http.options "http://httpbin.org" options : (Text | Uri) -> Vector.Vector -> Response ! Request_Error options uri (headers = []) = here.new.options uri headers @@ -80,18 +75,33 @@ options uri (headers = []) = here.new.options uri headers - headers: Any headers for the options request. > Example - Send a Get request. - Http.get "http://httpbin.org/get" + Send a Get request. NOTE: This example will make a network request. + + import Standard.Base.Network.Http + + example_get = Http.get "http://httpbin.org/get" > Example - Send authenticated Get request (note the use of TLS). - Http.get "https://httpbin.org/basic-auth/user/pass" [Header.authorization_basic "user" "pass"] + Send authenticated Get request (note the use of TLS). NOTE: This example + will make a network request. + + import Standard.Base.Network.Http + import Standard.Base.Network.Http.Header + + example_get = + headers = [Header.authorization_basic "user" "pass"] + Http.get "https://httpbin.org/basic-auth/user/pass" headers > Example - Download a file. - out_file = File.new "/tmp/out.bin" - res = Http.get "http://httpbin.org/bytes/1024" - res.body.to_file out_file + Download a file. NOTE: This example will make a network request. + + import Standard.Base.Network.Http + import Standard.Examples + + example_get = + out_file = Examples.scratch_file + res = Http.get "http://httpbin.org/bytes/1024" + res.body.to_file out_file get : (Text | Uri) -> Vector.Vector -> Response ! Request_Error get uri (headers = []) = here.new.get uri headers @@ -102,17 +112,33 @@ get uri (headers = []) = here.new.get uri headers - headers: Any headers for the options request. > Example - Send a Get request. - Http.fetch "http://httpbin.org/get" + Send a Get request and return the body. NOTE: This example will make a + network request. + + import Standard.Base.Network.Http + + example_fetch = Http.fetch "http://httpbin.org/get" > Example - Send authenticated Get request (note the use of TLS). - Http.fetch "https://httpbin.org/basic-auth/user/pass" [Header.authorization_basic "user" "pass"] + Send authenticated Get request (note the use of TLS) and return the body. + NOTE: This example will make a network request. + + import Standard.Base.Network.Http + import Standard.Base.Network.Http.Header + + example_fetch = + headers = [Header.authorization_basic "user" "pass"] + Http.fetch "https://httpbin.org/basic-auth/user/pass" headers > Example - Download a file. - out_file = File.new "/tmp/out.bin" - res = Http.fetch "http://httpbin.org/bytes/1024" . to_file out_file + Download a file. NOTE: This example will make a network request. + + import Standard.Base.Network.Http + import Standard.Examples + + example_fetch = + out_file = Examples.scratch_file + res = Http.fetch "http://httpbin.org/bytes/1024" . to_file out_file fetch : (Text | Uri) -> Vector.Vector -> Response ! Request_Error fetch uri (headers = []) = here.new.get uri headers . body @@ -124,9 +150,11 @@ fetch uri (headers = []) = - headers: Any headers for the options request. > Example - Send a Head request. - res = Http.head "http://httpbin.org" - IO.println res.headers + Send a Head request. NOTE: This example will make a network request. + + import Standard.Base.Network.Http + + example_head = Http.head "http://httpbin.org" head : (Text | Uri) -> Vector.Vector -> Response ! Request_Error head uri (headers = []) = here.new.options uri headers @@ -138,10 +166,17 @@ head uri (headers = []) = here.new.options uri headers - headers: Any headers for the options request. > Example - Send a Post request with binary data. - body = Body.Bytes "Hello".utf_8 - header_binary = Header.content_type "application/octet-stream" - Http.post "http://httpbin.org/post" body [header_binary] + Send a Post request with binary data. NOTE: This example will make a + network request. + + import Standard.Base.Network.Http + import Standard.Base.Network.Http.Header + import Standard.Base.Network.Http.Request.Body + + example_post = + body = Body.Bytes "Hello".utf_8 + header_binary = Header.content_type "application/octet-stream" + Http.post "http://httpbin.org/post" body [header_binary] post : (Text | Uri) -> Request_Body -> Vector.Vector -> Respoonse ! Request_Error post uri body (headers = []) = here.new.post uri body headers @@ -155,14 +190,27 @@ post uri body (headers = []) = here.new.post uri body headers - headers: Any headers for the options request. > Example - Send a Post request with form. - form = [Form.text_field "name" "John Doe", Form.file_field "license.txt" (Enso_Project.root / "LICENSE")] - Http.post_form "http://httpbin.org/post" form + Send a Post request with form. NOTE: This example will make a network + request. + + import Standard.Base.Network.Http + import Standard.Base.Network.Http.Form + + example_post_form = + form = [Form.text_field "name" "John Doe", Form.file_field "license.txt" (Enso_Project.root / "LICENSE")] + Http.post_form "http://httpbin.org/post" form > Example - Send a Post request with form encoded as "multipart/form-data". - form = [Form.text_field "name" "John Doe", Form.file_field "license.txt" (Enso_Project.root / "LICENSE")] - Http.post_form "http://httpbin.org/post" form [Header.multipart_form_data] + Send a Post request with form encoded as "multipart/form-data". NOTE: This + example will make a network request. + + import Standard.Base.Network.Http + import Standard.Base.Network.Http.Form + import Standard.Base.Network.Http.Header + + example_post_form = + form = [Form.text_field "name" "John Doe", Form.file_field "license.txt" (Enso_Project.root / "LICENSE")] + Http.post_form "http://httpbin.org/post" form [Header.multipart_form_data] post_form : (Text | Uri) -> (Vector | Form) -> Vector.Vector -> Response ! Request_Error post_form uri parts (headers = []) = here.new.post_form uri parts headers @@ -174,16 +222,22 @@ post_form uri parts (headers = []) = here.new.post_form uri parts headers - headers: Any headers for the options request. > Example - Send a Post request with json data. - json = Json.parse <| ''' - {"key":"val"} - Http.post_json "http://httpbin.org/post" json + Send a Post request with json data. NOTE: This example will make a network + request. + + import Standard.Base.Network.Http + + example_post_json = + json = Json.parse '{"key":"val"}' + Http.post_json "http://httpbin.org/post" json post_json : (Text | Uri) -> Json -> Vector.Vector -> Response ! Request_Error post_json uri body_json (headers = []) = here.new.post_json uri body_json headers type Http - ## An HTTP client. + ## PRIVATE + + An HTTP client. Arguments: - timeout: The length of time the client will wait for responses. @@ -199,8 +253,12 @@ type Http - headers: Any headers for the options request. > Example - Send an Options request. - Http.new.options "http://httpbin.org" + Send an Options request. NOTE: This example will make a network + request. + + import Standard.Examples + + example_options = Examples.http_client.options "http://httpbin.org" options : (Text | Uri) -> Vector.Vector -> Response ! Request_Error options uri (headers = []) = req = Request.options uri headers @@ -213,18 +271,32 @@ type Http - headers: Any headers for the options request. > Example - Send a Get request. - Http.new.get "http://httpbin.org/get" + Send a Get request. NOTE: This example will make a network request. + + import Standard.Examples + + example_get = Examples.http_client.get "http://httpbin.org/get" > Example - Send authenticated Get request (note the use of TLS). - Http.new.get "https://httpbin.org/basic-auth/user/pass" [Header.authorization_basic "user" "pass"] + Send authenticated Get request (note the use of TLS). NOTE: This + example will make a network request. + + import Standard.Base.Network.Http.Header + import Standard.Examples + + example_get = + headers = [Header.authorization_basic "user" "pass"] + Examples.http_client.get "https://httpbin.org/basic-auth/user/pass" headers > Example - Download a file. - out_file = File.new "/tmp/out.bin" - res = Http.new.get "http://httpbin.org/bytes/1024" - res.body.to_file out_file + Download a file. NOTE: This example will make a network request. + + import Standard.Examples + + example_get = + out_file = Examples.scratch_file + res = Examples.http_client.get "http://httpbin.org/bytes/1024" + res.body.to_file out_file get : (Text | Uri) -> Vector.Vector -> Response ! Request_Error get uri (headers = []) = req = Request.get uri headers @@ -236,10 +308,13 @@ type Http - uri: The address to which the request will be sent. - headers: Any headers for the options request. + > Example - Send a Head request. - res = Http.new.head "http://httpbin.org" - IO.println res.headers + Send a Head request. NOTE: This example will make a network request. + + import Standard.Examples + + example_head = Examples.http_client.head "http://httpbin.org" head : (Text | Uri) -> Vector.Vector -> Response ! Request_Error head uri (headers = []) = req = Request.head uri headers @@ -252,11 +327,18 @@ type Http - body: The body of the post request. - headers: Any headers for the options request. + > Example - Send a Post request with binary data. - body = Body.Bytes "Hello".utf_8 - header_binary = Header.content_type "application/octet-stream" - Http.new.post "http://httpbin.org/post" body [header_binary] + Send a Post request with binary data. NOTE: This example will make a + network request. + + import Standard.Base.Network.Http.Header + import Standard.Base.Network.Http.Request.Body + import Standard.Examples + + example_post = + body = Body.Bytes "Hello".utf_8 + Examples.http_client.post "http://httpbin.org/post" body [header_binary] post : (Text | Uri) -> Request_Body -> Vector.Vector -> Respoonse ! Request_Error post uri body (headers = []) = req = Request.post uri body headers @@ -271,21 +353,29 @@ type Http - parts: A form, or the parts for creating a form. - headers: Any headers for the options request. - > Example - Send a Post request with form. - form = [Form.text_field "name" "John Doe", Form.file_field "license.txt" (Enso_Project.root / "LICENSE")] - Http.new.post_form "http://httpbin.org/post" form > Example - Send a Post request with form encoded as "multipart/form-data". - form = [Form.text_field "name" "John Doe", Form.file_field "license.txt" (Enso_Project.root / "LICENSE")] - Http.new.post_form "http://httpbin.org/post" form [Header.multipart_form_data] + Send a Post request with form. NOTE: This example will make a network + request. + + import Standard.Base.Network.Http.Form + import Standard.Examples + + example_post_form = + form = [Form.text_field "name" "John Doe", Form.file_field "license.txt" (Enso_Project.root / "LICENSE")] + Examples.http_client.post_form "http://httpbin.org/post" form > Example - Configure HTTP client and send a Post request. - form = [Form.text_field "name" "John Doe", Form.file_field "license.txt" (Enso_Project.root / "LICENSE")] - http = Http.new (timeout = 30.seconds) - http.post_form "http://httpbin.org/post" form + Send a Post request with form encoded as "multipart/form-data". NOTE: This + example will make a network request. + + import Standard.Base.Network.Http.Form + import Standard.Base.Network.Http.Header + import Standard.Examples + + example_post_form = + form = [Form.text_field "name" "John Doe", Form.file_field "license.txt" (Enso_Project.root / "LICENSE")] + Examples.http_client.post_form "http://httpbin.org/post" form [Header.multipart_form_data] post_form : (Text | Uri) -> (Vector | Form) -> Vector.Vector -> Response ! Request_Error post_form uri parts (headers = []) = new_headers = [Header.application_x_www_form_urlencoded] @@ -299,11 +389,16 @@ type Http - body_json: The JSON body for the post request. - headers: Any headers for the options request. + > Example - Send a Post request with json data. - json = Json.parse <| ''' - {"key":"val"} - Http.new.post_json "http://httpbin.org/post" json + Send a Post request with json data. NOTE: This example will make a network + request. + + import Standard.Examples + + example_post_json = + json = Json.parse '{"key":"val"}' + Examples.http_client.post_json "http://httpbin.org/post" json post_json : (Text | Uri) -> Json -> Vector.Vector -> Response ! Request_Error post_json uri body_json (headers = []) = new_headers = [Header.application_json] @@ -319,9 +414,14 @@ type Http > Example Send a Put request with binary data. - body = Body.Bytes "contents".utf_8 - header_binary = Header.content_type "application/octet-stream" - Http.new.put "http://httpbin.org/post" body [header_binary] + + import Standard.Base.Network.Http.Header + import Standard.Base.Network.Http.Request.Body + import Standard.Examples + + example_put = + body = Body.Bytes "contents".utf_8 + Examples.http_client.put "http://httpbin.org/post" body [header_binary] put : (Text | Uri) -> Request_Body -> Vector.Vector -> Respoonse ! Request_Error put uri body (headers = []) = req = Request.put uri body headers @@ -335,10 +435,14 @@ type Http - headers: Any headers for the options request. > Example - Send a Put request with json data. - json = Json.parse <| ''' - {"key":"val"} - Http.new.put_json "http://httpbin.org/put" json + Send a Put request with json data. NOTE: This example will make a + network request. + + import Standard.Examples + + example_post_json = + json = Json.parse '{"key":"val"}' + Examples.http_client.put_json "http://httpbin.org/post" json put_json : (Text | Uri) -> Json -> Vector.Vector -> Response ! Request_Error put_json uri body_json (headers = []) = new_headers = [Header.application_json] @@ -352,8 +456,11 @@ type Http - headers: Any headers for the options request. > Example - Send a Delete request. - Http.new.delete "http://httpbin.org/delete" + Send a Delete request. NOTE: This example will make a network request. + + import Standard.Examples + + example_delete = Examples.http_client.delete "http://httpbin.org/delete" delete : (Text | Uri) -> Vector.Vector -> Response ! Request_Error delete uri (headers = []) = req = Request.delete uri headers @@ -365,35 +472,80 @@ type Http - req: The HTTP request to send using `this` HTTP client. > Example - Send a Get request with headers. - req = Request.new Method.Get "http://httpbin.org/get" . with_header "X-Trace-Id" "00000" - res = Http.new.request req - res.body + Send a Get request with headers. NOTE: This example will send a network + request. + + import Standard.Base.Network.Http + import Standard.Base.Network.Http.Method + import Standard.Base.Network.Http.Request + + example_request = + req = Request.new Method.Get "http://httpbin.org/get" . with_header "X-Trace-Id" "00000" + res = Examples.http_client.request req + res.body > Example - Open a connection and send a Post request with form. - req = Request.post "http://httpbin.org/post" . with_form [Form.text_field "key" "value"] . with_header "X-Trace-Id" "123456789" - res = http.new.request req - res.code + Open a connection and send a Post request with form. NOTE: This example + will send a network request. + + import Standard.Base.Network.Http.Form + import Standard.Base.Network.Http.Request + import Standard.Base.Network.Http.Request.Body + import Standard.Examples + + example_request = + req = Request.post "http://httpbin.org/post" Body.Empty + with_form = req.with_form [Form.text_field "key" "value"] + with_header = with_form.with_header "X-Trace-Id" "123456789" + res = Examples.http_client.request with_header + res.code > Example - Send a Post request with urlencoded form data. - form = [Form.text_field "name" "John Doe", Form.file_field "license.txt" (Enso_Project.root / "LICENSE")] - req = Request.post "http://httpbin.org/post" . with_form form - Http.new.request req + Send a Post request with urlencoded form data. NOTE: This example will + send a network request. + + import Standard.Base.Network.Http.Form + import Standard.Base.Network.Http.Request + import Standard.Base.Network.Http.Request.Body + import Standard.Examples + + example_request = + form = [Form.text_field "name" "John Doe", Form.file_field "license.txt" (Enso_Project.root / "LICENSE")] + req = Request.post "http://httpbin.org/post" Body.Empty . with_form form + Examples.http_client.request req > Example - Send a Post request with form encoded as "multipart/form-data". - form = [Form.text_field "name" "John Doe", Form.file_field "license.txt" (Enso_Project.root / "LICENSE")] - req = Request.post "http://httpbin.org/post" . with_form form . with_headers [Header.multipart_form_data] - Http.new.post req + Send a Post request with form encoded as "multipart/form-data". NOTE: + This example will send a network request. + + import Standard.Base.Network.Http.Form + import Standard.Base.Network.Http.Header + import Standard.Base.Network.Http.Request + import Standard.Base.Network.Http.Request.Body + import Standard.Examples + + example_request = + form = [Form.text_field "name" "John Doe", Form.file_field "license.txt" (Enso_Project.root / "LICENSE")] + req = Request.post "http://httpbin.org/post" Body.Empty + with_form = req.with_form form + with_headers = with_form.with_headers [Header.multipart_form_data] + Examples.http_client.request with_headers > Example - Configure HTTP client and send a Post request with form. - form = [Form.text_field "name" "John Doe"] - req = Request.new Method.Post "http://httpbin.org/post" . with_form form - http = Http.new (timeout = 30.seconds) (proxy = Proxy.new "proxy.example.com:80") - http.request req + Configure HTTP client and send a Post request with form. NOTE: This + example will send a network request. + + import Standard.Base.Data.Time.Duration + import Standard.Base.Network.Http + import Standard.Base.Network.Http.Form + import Standard.Base.Network.Http.Method + import Standard.Base.Network.Http.Request + + example_request = + form = [Form.text_field "name" "John Doe"] + req = Request.new Method.Post "http://httpbin.org/post" . with_form form + http = Http.new (timeout = 30.seconds) + http.request req request : Request -> Response ! Request_Error request req = response = Panic.recover <| @@ -427,10 +579,14 @@ type Http Pair req body_builder.build if req.headers.contains Header.multipart_form_data then add_multipart form else add_urlencoded form + Request_Body.Bytes bytes -> + builder.header Header.application_octet_stream.name Header.application_octet_stream.value + Pair req (body_publishers.ofByteArray bytes.to_array) # method req_http_method = case req.method of Method.Options -> "OPTIONS" Method.Get -> "GET" + Method.Head -> "HEAD" Method.Post -> "POST" Method.Put -> "PUT" Method.Delete -> "DELETE" @@ -484,3 +640,17 @@ type Http builder.version HttpClient.Version.HTTP_2 # build http client builder.build + +## UNSTABLE + + An error when sending an Http request. + + Arguments: + - message: The message for the error. +type Request_Error message + +## UNSTABLE + + Convert a request error to a human-readable form. +Request_Error.to_display_text = "Error when sending request: " + this.message + diff --git a/distribution/std-lib/Standard/src/Base/Network/Http/Form.enso b/distribution/std-lib/Standard/src/Base/Network/Http/Form.enso index ca0c8d09705..af0c00da275 100644 --- a/distribution/std-lib/Standard/src/Base/Network/Http/Form.enso +++ b/distribution/std-lib/Standard/src/Base/Network/Http/Form.enso @@ -2,6 +2,52 @@ from Standard.Base import all import Standard.Base.Data.Vector +## Create Form data from Parts. + + Arguments: + - parts: A vector of parts to make up the form. + + > Example + Create a new form + + import Standard.Base.Network.Http.Form + + example_form_new = Form.new (Form.text_field "foo" "bar") +new : Vector.Vector -> Form +new parts = Form parts + +# Helpers for creating different parts of the form. + +## Create a text field of a Form. + + Arguments: + - key: The key for the field in the form. + - val: The text for the textual field. + + > Example + Create a textual form field. + + import Standard.Base.Network.Http.Form + + example_text_field = Form.text_field "Foo" "bar" +text_field : Text -> Text -> Part +text_field key val = Part key (Part_Text val) + +## Create a file field of a Form. + + Arguments: + - key: The key for the field in the form. + - file: The textual file contents. + + > Example + Create a file form field. + + import Standard.Base.Network.Http.Form + + example_text_field = Form.file_field "Foo" "My file contents" +file_field : Text -> Text -> Part +file_field key file = Part key (Part_File file) + ## The HTTP form containing a vector of parts. type Form @@ -17,11 +63,24 @@ type Form > Example Convert to a form. - Form.new [Part "foo" (Part_Text "bar")] . to_form + + import Standard.Base.Network.Http.Form + + example_to_form = Form.new [Part "foo" (Part_Text "bar")] . to_form to_form : Form to_form = this ## Convert Vector to a Form. + + > Example + Create a vector of form parts and convert it to a form. + + import Standard.Base.Network.Http.Form + + example_to_form = + part_1 = Form.text_field "Foo" "bar" + part_2 = Form.text_field "Baz" "quux" + [part_1, part_2].to_form Vector.Vector.to_form = Form this ## The key-value element of the form. @@ -48,41 +107,3 @@ type Part_Value Arguments: - part_file: The file for the form part. type Part_File part_file - -## Create Form data from Parts. - - Arguments: - - parts: A vector of parts to make up the form. - - > Example - Create a new form - Form.new (Form.text_field "foo" "bar") -new : Vector.Vector -> Form -new parts = Form parts - -# Helpers for creating different parts of the form. - -## Create a text field of a Form. - - Arguments: - - key: The key for the field in the form. - - val: The text for the textual field. - - > Example - Create a textual form field. - Form.text_field "Foo" "bar" -text_field : Text -> Text -> Part -text_field key val = Part key (Part_Text val) - -## Create a file field of a Form. - - Arguments: - - key: The key for the field in the form. - - file: The textual file contents. - - > Example - Create a file form field. - Form.file_field "Foo" "My file contents" -file_field : Text -> Text -> Part -file_field key file = Part key (Part_File file) - diff --git a/distribution/std-lib/Standard/src/Base/Network/Http/Header.enso b/distribution/std-lib/Standard/src/Base/Network/Http/Header.enso index b801a451721..9f35fb117c3 100644 --- a/distribution/std-lib/Standard/src/Base/Network/Http/Header.enso +++ b/distribution/std-lib/Standard/src/Base/Network/Http/Header.enso @@ -2,6 +2,156 @@ from Standard.Base import all polyglot java import org.enso.base.Http_Utils +## Create a new Header. + + Arguments: + - name: The name of the header. + - value: The value for the header. + + > Example + Create a new header called "My_Header". + + import Standard.Base.Network.Http.Header + + example_new = Header.new "My_Header" "my header's value" +new : Text -> Text -> Header +new name value = Header name value + +# Accept + +## Create an "Accept" header. + + Arguments: + - value: The value for the accept header. + + > Example + Create an accept header. + + import Standard.Base.Network.Http.Header + + example_accept = Header.accept "my_field" +accept : Text -> Header +accept value = Header "Accept" value + +## Create a header that accepts all (`"*/*"`). + + > Example + Create an accept all header. + + import Standard.Base.Network.Http.Header + + example_accept_all = Header.accept_all +accept_all : Header +accept_all = here.accept "*/*" + +# Authorization + +## Create "Authorization" header. + + Arguments: + - value: The value for the authorization header. + + > Example + Create an auth header containing "foo". + + import Standard.Base.Network.Http.Header + + example_auth = Header.authorization "foo" +authorization : Text -> Header +authorization value = Header "Authorization" value + +## Create HTTP basic auth header. + + Arguments: + - user: The username. + - pass: The password. + + > Example + Create basic auth header. + + import Standard.Base.Network.Http.Header + + example_auth_basic = Header.authorization_basic "user" "pass" +authorization_basic : Text -> Text -> Header +authorization_basic user pass = + here.authorization (Http_Utils.header_basic_auth user pass) + +# Content-Type + +## Create "Content-Type" header. + + Arguments: + - value: The value for the content type header. + + > Example + Create a content type header containing "my_type". + + import Standard.Base.Network.Http.Header + + example_content_type = Header.content_type "my_type" +content_type : Text -> Header +content_type value = Header "Content-Type" value + +## Header "Content-Type: application/json". + + > Example + Create a header with content type "application/json". + + import Standard.Base.Network.Http.Header + + example_app_json = Header.application_json +application_json : Header +application_json = here.content_type "application/json" + +## Header "Content-Type: application/octet-stream". + + > Example + Create a header with content type "application/octet-stream". + + import Standard.Base.Network.Http.Header + + example_app_octet = Header.application_octet_stream +application_octet_stream : Header +application_octet_stream = here.content_type "application/octet-stream" + +## Header "Content-Type: application/x-www-form-urlencoded". + + > Example + Create a header with content type "application/x-www-form-urlencoded". + + import Standard.Base.Network.Http.Header + + example_app_x_www = Header.application_x_www_form_urlencoded +application_x_www_form_urlencoded : Header +application_x_www_form_urlencoded = here.content_type "application/x-www-form-urlencoded" + +## Header "Content-Type: multipart/form-data". + + Arguments: + - boundary: The text that delimits boundaries between the parts of the form. + + > Example + Create a header with content type "multipart/form-data". + + import Standard.Base.Network.Http.Header + + example_multipart = Header.multipart_form_data +multipart_form_data : Text -> Header +multipart_form_data (boundary = "") = + if boundary == "" then here.content_type "multipart/form-data" else + here.content_type ("multipart/form-data; boundary=" + boundary) + +## Header "Content-Type: text/plain". + + > Example + Create a header with the content type "text/plain". + + import Standard.Base.Network.Http.Header + + example_header_text_plain = Header.text_plain +text_plain : Header +text_plain = here.content_type "text/plain" + type Header ## PRIVATE @@ -20,123 +170,11 @@ type Header > Example Compare two headers. - (Header.new "My_Header" "foo") == (Header.new "My_Header" "bar") + + import Standard.Base.Network.Http.Header + + example_header_eq = + (Header.new "My_Header" "foo") == (Header.new "My_Header" "bar") == : Header -> Boolean == that = (this.name.equals_ignore_case that.name) && this.value==that.value -## Create a new Header. - - Arguments: - - name: The name of the header. - - value: The value for the header. - - > Example - Create a new header called "My_Header". - Header.new "My_Header" "my header's value" -new : Text -> Text -> Header -new name value = Header name value - -# Accept - -## Create an "Accept" header. - - Arguments: - - value: The value for the accept header. - - > Example - Create an accept header. - Header.accept "my_field" -accept : Text -> Header -accept value = Header "Accept" value - -## Create a header that accepts all (`"*/*"`). - - > Example - Create an accept all header. - Header.accept_all -accept_all : Header -accept_all = here.accept "*/*" - -# Authorization - -## Create "Authorization" header. - - Arguments: - - value: The value for the authorization header. - - > Example - Create an auth header containing "foo". - Header.authorization "foo" -authorization : Text -> Header -authorization value = Header "Authorization" value - -## Create HTTP basic auth header. - - Arguments: - - user: The username. - - pass: The password. - - > Example - Create basic auth header. - Header.authorization_basic "user" "pass" -authorization_basic : Text -> Text -> Header -authorization_basic user pass = - here.authorization (Http_Utils.header_basic_auth user pass) - -# Content-Type - -## Create "Content-Type" header. - - Arguments: - - value: The value for the content type header. - - > Example - Create a content type header containing "my_type". - Header.content_type "my_type" -content_type : Text -> Header -content_type value = Header "Content-Type" value - -## Header "Content-Type: application/json". - - > Example - Create a header with content type "application/json". - Header.application_json -application_json : Header -application_json = here.content_type "application/json" - -## Header "Content-Type: application/octet-stream". - - > Example - Create a header with content type "application/octet-stream". - Header.application_octet_stream -application_octet_stream : Header -application_octet_stream = here.content_type "application/octet-stream" - -## Header "Content-Type: application/x-www-form-urlencoded". - - > Example - Create a header with content type "application/x-www-form-urlencoded". - Header.application_x_www_form_urlencoded -application_x_www_form_urlencoded : Header -application_x_www_form_urlencoded = here.content_type "application/x-www-form-urlencoded" - -## Header "Content-Type: multipart/form-data". - - Arguments: - - boundary: The text that delimits boundaries between the parts of the form. - - > Example - Create a header with content type "multipart/form-data". - Header.multipart_form_data -multipart_form_data : Text -> Header -multipart_form_data (boundary = "") = - if boundary == "" then here.content_type "multipart/form-data" else - here.content_type ("multipart/form-data; boundary=" + boundary) - -## Header "Content-Type: text/plain". - - > Example - Create a header with the content type "text/plain". - Header.text_plain -text_plain : Header -text_plain = here.content_type "text/plain" diff --git a/distribution/std-lib/Standard/src/Base/Network/Http/Request.enso b/distribution/std-lib/Standard/src/Base/Network/Http/Request.enso index 0b9d7e9eb2d..9957a49f66c 100644 --- a/distribution/std-lib/Standard/src/Base/Network/Http/Request.enso +++ b/distribution/std-lib/Standard/src/Base/Network/Http/Request.enso @@ -20,7 +20,12 @@ polyglot java import org.enso.base.Text_Utils > Example Create a new post request with no headers and no body. - Request.new Method.Post (Uri.parse "http://example.com") + + import Standard.Base.Network.Http.Method + import Standard.Base.Network.Http.Request + import Standard.Base.Network.Uri + + example_new = Request.new Method.Post (Uri.parse "http://example.com") new : Method -> (Text | Uri) -> Vector.Vector -> Request_Body -> Request new method addr (headers = []) (body = Request_Body.Empty) = Panic.recover (Request method (Internal.panic_on_error (addr.to_uri)) headers body) . catch Internal.recover_panic @@ -31,7 +36,11 @@ new method addr (headers = []) (body = Request_Body.Empty) = > Example Create a new options request. - Request.options (Uri.parse "http://example.com") + + import Standard.Base.Network.Http.Request + import Standard.Base.Network.Uri + + example_options = Request.options (Uri.parse "http://example.com") options : (Text | Uri) -> Vector.Vector -> Request options addr (headers = []) = here.new Method.Options addr headers @@ -43,7 +52,11 @@ options addr (headers = []) = here.new Method.Options addr headers > Example Create a new get request. - Request.get (Uri.parse "http://example.com") + + import Standard.Base.Network.Http.Request + import Standard.Base.Network.Uri + + example_get = Request.get (Uri.parse "http://example.com") get : (Text | Uri) -> Vector.Vector -> Request get addr (headers = []) = here.new Method.Get addr headers @@ -55,7 +68,11 @@ get addr (headers = []) = here.new Method.Get addr headers > Example Create a new head request. - Request.head (Uri.parse "http://example.com") + + import Standard.Base.Network.Http.Request + import Standard.Base.Network.Uri + + example_head = Request.head (Uri.parse "http://example.com") head : (Text | Uri) -> Vector.Vector -> Request head addr (headers = []) = here.new Method.Head addr headers @@ -68,7 +85,12 @@ head addr (headers = []) = here.new Method.Head addr headers > Example Create a new post request. - Request.post (Uri.parse "http://example.com") Request_Body.Empty + + import Standard.Base.Network.Http.Request + import Standard.Base.Network.Http.Request.Body as Request_Body + import Standard.Base.Network.Uri + + example_post = Request.post (Uri.parse "http://example.com") Request_Body.Empty post : (Text | Uri) -> Request_Body -> Vector.Vector -> Request post addr body (headers = []) = here.new Method.Post addr headers body @@ -81,7 +103,12 @@ post addr body (headers = []) = here.new Method.Post addr headers body > Example Create a new put request. - Request.put (Uri.parse "http://example.com") Request_Body.Empty + + import Standard.Base.Network.Http.Request + import Standard.Base.Network.Http.Request.Body as Request_Body + import Standard.Base.Network.Uri + + example_put = Request.put (Uri.parse "http://example.com") Request_Body.Empty put : (Text | Uri) -> Request_Body -> Vector.Vector -> Request put addr body (headers = []) = here.new Method.Put addr headers body @@ -93,7 +120,11 @@ put addr body (headers = []) = here.new Method.Put addr headers body > Example Create a new delete request. - Request.delete (Uri.parse "http://example.com") + + import Standard.Base.Network.Http.Request + import Standard.Base.Network.Uri + + example_delete = Request.delete (Uri.parse "http://example.com") delete : (Text | Uri) -> Vector.Vector -> Request delete addr (headers = []) = here.new Method.Delete addr headers @@ -118,7 +149,10 @@ type Request > Example Create a request and add a new header to it. - Request.delete.with_header "Foo" "bar" + + import Standard.Base.Network.Http.Request + + example_with_header = Request.delete.with_header "Foo" "bar" with_header : Text -> Text -> Request with_header key val = new_header = Header.new key val @@ -139,7 +173,10 @@ type Request > Example Create a request and unset all the headers. - Request.delete.with_headers [] + + import Standard.Base.Network.Http.Request + + example_with_headers = Request.delete.with_headers [] with_headers : [Header] -> Request with_headers new_headers = update_header req new_header = req.with_header new_header.name new_header.value @@ -152,7 +189,13 @@ type Request > Example Unsetting the body in a post request. - Request.post (Uri.parse "http://example.com") Request_Body.Empty |> .with_body Request_Body.Empty + + import Standard.Base.Network.Http.Request + import Standard.Base.Network.Http.Request.Body as Request_Body + import Standard.Base.Network.Uri + + example_with_body = + Request.post (Uri.parse "http://example.com") Request_Body.Empty |> .with_body Request_Body.Empty with_body : Request_Body -> Request with_body new_body = Request this.method this.uri this.headers new_body @@ -164,7 +207,13 @@ type Request > Example Setting the body in a post request to some JSON. - Request.post (Uri.parse "http://example.com") Request_Body.Empty |> .with_body "{ "a": "b" }" + + import Standard.Base.Network.Http.Request + import Standard.Base.Network.Http.Request.Body as Request_Body + import Standard.Base.Network.Uri + + example_with_json = + Request.post (Uri.parse "http://example.com") Request_Body.Empty |> .with_body "{ "a": "b" }" with_json : Text -> Request with_json json_body = new_body = Request_Body.Json json_body @@ -177,7 +226,12 @@ type Request > Example Create a delete request with an empty form. - Request.delete (Uri.parse "http://example.com") . with_form [] + + import Standard.Base.Network.Http.Request + import Standard.Base.Network.Uri + + example_delete = + Request.delete (Uri.parse "http://example.com") . with_form [] with_form : (Vector | Form) -> Request with_form parts = new_body = Request_Body.Form parts.to_form diff --git a/distribution/std-lib/Standard/src/Base/Network/Http/Response.enso b/distribution/std-lib/Standard/src/Base/Network/Http/Response.enso index c37f79d4566..fe3c0744953 100644 --- a/distribution/std-lib/Standard/src/Base/Network/Http/Response.enso +++ b/distribution/std-lib/Standard/src/Base/Network/Http/Response.enso @@ -19,19 +19,52 @@ type Response type Response internal_http_response ## Get the response headers. + + > Example + Getting the headers from a response. NOTE that this example will make a + network request. + + import Standard.Examples + + example_headers = Examples.get_response.headers headers : Vector.Vector headers = header_entries = Vector.vector (Http_Utils.get_headers this.internal_http_response.headers) header_entries.map e-> Header.new e.getKey e.getValue ## Get the response body. + + > Example + Getting the body from a response. NOTE that this example will make a + network request. + + import Standard.Examples + + example_body = Examples.get_response.body body : Response_Body body = Response_Body.body (Vector.vector this.internal_http_response.body) ## Get the response status code. + + > Example + Getting the code from a response. NOTE that this example will make a + network request. + + import Standard.Examples + + example_code = Examples.get_response.code code : Status_Code code = Status_Code.status_code this.internal_http_response.statusCode ## Convert the response to JSON. + + > Example + Convert a response to JSON. NOTE that this example will make a network + request. + + import Standard.Examples + + example_to_json = Examples.get_response.to_json to_json : Json.Object to_json = Json.from_pairs [["type", "Response"], ["headers", this.headers], ["body", this.body], ["code", this.code]] + diff --git a/distribution/std-lib/Standard/src/Base/Network/Http/Response/Body.enso b/distribution/std-lib/Standard/src/Base/Network/Http/Response/Body.enso index acf75f35a38..6833a17e185 100644 --- a/distribution/std-lib/Standard/src/Base/Network/Http/Response/Body.enso +++ b/distribution/std-lib/Standard/src/Base/Network/Http/Response/Body.enso @@ -12,10 +12,24 @@ type Body type Body bytes ## Convert response body to Text. + + > Example + Convert a response to text. NOTE: This example makes a network request. + + import Standard.Examples + + example_to_text = Examples.get_geo_data.to_text to_text : Text to_text = Text.from_utf_8 this.bytes ## Convert response body to Json. + + > Example + Convert a response to JSON. NOTE: This example makes a network request. + + import Standard.Examples + + example_to_text = Examples.get_geo_data.to_json to_json : Json to_json = Json.parse this.to_text @@ -23,7 +37,18 @@ type Body Arguments: - file: The file to write the bytes to. + + > Examples + Write the contents of the request body to a scratch file on disk. The + file will be created if it does not exist, and will be overwritten if + it does. + + import Standard.Examples + + example_to_file = + Examples.get_geo_data.to_file Examples.scratch_file to_file : File -> File to_file file = file.write_bytes this.bytes file + diff --git a/distribution/std-lib/Standard/src/Base/Network/Proxy.enso b/distribution/std-lib/Standard/src/Base/Network/Proxy.enso index 36be2a4425e..53e172d1074 100644 --- a/distribution/std-lib/Standard/src/Base/Network/Proxy.enso +++ b/distribution/std-lib/Standard/src/Base/Network/Proxy.enso @@ -20,6 +20,9 @@ type Proxy > Example Create a new proxy running on localhost at port 80080. - Proxy.new "localhost" 80800 + + import Standard.Base.Network.Proxy + + example_new = Proxy.new "localhost" 80800 new : Text -> Integer -> Proxy new host port=80 = Proxy_Addr host port diff --git a/distribution/std-lib/Standard/src/Base/Network/Uri.enso b/distribution/std-lib/Standard/src/Base/Network/Uri.enso index 952c49eadfc..2aa93e68f9a 100644 --- a/distribution/std-lib/Standard/src/Base/Network/Uri.enso +++ b/distribution/std-lib/Standard/src/Base/Network/Uri.enso @@ -5,16 +5,6 @@ import Standard.Base.Network.Uri.Internal polyglot java import java.net.URI as Java_URI polyglot java import java.util.Optional -## Syntax error when parsing a Uri. - - Arguments: - - message: The error message for the URI syntax error. -type Syntax_Error message - -## Converts the URI syntax error to a human-readable form. -Syntax_Error.to_display_text = - "Uri syntax error: " + this.message - ## Parse a Uri from text. Arguments: @@ -24,7 +14,10 @@ Syntax_Error.to_display_text = > Example Parse Uri text. - Uri.parse "http://example.com" + + import Standard.Base.Network.Uri + + example_parse = Uri.parse "http://example.com" parse : Text -> Uri ! Syntax_Error parse text = Panic.recover (Uri (Java_URI.create text)) . catch e-> case e of @@ -37,13 +30,18 @@ parse text = > Example Parse Uri text. - Uri.parse "http://example.com" + + import Standard.Base.Network.Uri + + example_parse = "http://example.com".to_uri Text.to_uri : Uri ! Syntax_Error Text.to_uri = here.parse this type Uri - ## Represents a Uniform Resource Identifier (URI) reference. + ## PRIVATE + + Represents a Uniform Resource Identifier (URI) reference. Arguments: - internal_uri: The internal representation of the URI. @@ -53,57 +51,65 @@ type Uri > Examples Convert a URI to a URI (a no op). - "http://example.com".to_uri.to_uri + + import Standard.Examples + + example_to_uri = Examples.uri.to_uri to_uri : Uri to_uri = this ## Get the scheme part of this Uri. > Example - Return the "http" part of the HTTP address. - addr = "http://user:pass@example.com/foo/bar?key=val" - Uri.parse addr . scheme + Return the scheme from the URI. + + import Standard.Examples + + example_scheme = Examples.uri.scheme scheme : Text ! Nothing scheme = Internal.handle_nothing this.internal_uri.getScheme ## Get the user info part of this Uri. > Example - Return the "user:pass" part of the HTTP address. - addr = "http://user:pass@example.com/foo/bar?key=val" - Uri.parse addr . user_info + Return the user info part of the URI. + + import Standard.Examples + + example_user_info = Examples.uri.user_info user_info : Text ! Nothing user_info = Internal.handle_nothing this.internal_uri.getUserInfo ## Get the host part of this Uri. > Example - Return the "example.com" part of the HTTP address. - addr = "http://user:pass@example.com/foo/bar?key=val" - Uri.parse addr . host + Return the host portion of the URI. + + import Standard.Examples + + example_host = Examples.uri.host host : Text ! Nothing host = Internal.handle_nothing this.internal_uri.getHost ## Get the authority (user info and host) part of this Uri. > Example - Return the "user:pass@example.com" part of the HTTP address. - addr = "http://user:pass@example.com/foo/bar?key=val" - Uri.parse addr . authority + Return the authority portion of the URI. + + import Standard.Examples + + example_authority = Examples.uri.authority authority : Text ! Nothing authority = Internal.handle_nothing this.internal_uri.getAuthority ## Get the port part of this Uri. > Example - Return the "80" part of the HTTP address. - addr = "http://user:pass@example.com:80/foo/bar?key=val" - Uri.parse addr . port + Return the port portion of the URI - > Example - Return the empty string if the port is not specified. - addr = "http://user:pass@example.com:80/foo/bar?key=val" - Uri.parse addr . port + import Standard.Examples + + example_port = Examples.uri.port port : Text ! Nothing port = port_number = this.internal_uri.getPort @@ -113,27 +119,33 @@ type Uri ## Get the path part of this Uri. > Example - Return the "/foo/bar" part of the HTTP address. - addr = "http://user:pass@example.com:80/foo/bar?key=val" - Uri.parse addr . path + Return the path portion of the URI. + + import Standard.Examples + + example_path = Examples.uri.path path : Text ! Nothing path = Internal.handle_nothing this.internal_uri.getPath ## Get the query part of this Uri. > Example - Return the "key=val" part of the HTTP address. - addr = "http://user:pass@example.com:80/foo/bar?key=val" - Uri.parse addr . query + Return the query portion of the URI. + + import Standard.Examples + + example_query = Examples.uri.query query : Text ! Nothing query = Internal.handle_nothing this.internal_uri.getQuery ## Get the fragment part of this Uri. > Example - Return the empty fragment of the HTTP address. - addr = "http://user:pass@example.com:80/foo/bar?key=val" - Uri.parse addr . fragment + Return the fragment portion of the URI. + + import Standard.Examples + + example_fragment = Examples.uri.fragment fragment : Text ! Nothing fragment = Internal.handle_nothing this.internal_uri.getFragment @@ -171,7 +183,10 @@ type Uri > Example Convert a URI to text. - Uri.new "https://example.com" . to_text + + import Standard.Examples + + example_to_text = Examples.uri.to_text to_text : Text to_text = this.internal_uri.toString @@ -179,7 +194,11 @@ type Uri > Example Convert a URI to JSON. - Uri.new "https://example.com" . to_json + + import Standard.Base.Network.Uri + import Standard.Examples + + example_to_json = Examples.uri.to_json to_json : Json.String to_json : Json.String this.to_text @@ -187,7 +206,24 @@ type Uri > Example Check if two URIs are equal. - "https://example.com" == "http://example.com" + + import Standard.Base.Network.Uri + + example_eq = "https://example.com".to_uri == "http://example.org".to_uri == : Uri -> Boolean == that = this.internal_uri.equals that.internal_uri +## UNSTABLE + + Syntax error when parsing a Uri. + + Arguments: + - message: The error message for the URI syntax error. +type Syntax_Error message + +## UNSTABLE + + Converts the URI syntax error to a human-readable form. +Syntax_Error.to_display_text = + "Uri syntax error: " + this.message + diff --git a/distribution/std-lib/Standard/src/Base/System/Environment.enso b/distribution/std-lib/Standard/src/Base/System/Environment.enso index d5aab1c5021..dcbbb831f10 100644 --- a/distribution/std-lib/Standard/src/Base/System/Environment.enso +++ b/distribution/std-lib/Standard/src/Base/System/Environment.enso @@ -12,7 +12,9 @@ polyglot java import java.lang.System > Example Look up the value of the `PATH` environment variable. - Environment.get "PATH" + + import Standard.Base.System.Environment + + example_get = Environment.get "PATH" get : Text -> Text | Nothing -get key = - System.getenv key +get key = System.getenv key diff --git a/distribution/std-lib/Standard/src/Base/System/File.enso b/distribution/std-lib/Standard/src/Base/System/File.enso index 45af44c5a6a..f40cd7004c0 100644 --- a/distribution/std-lib/Standard/src/Base/System/File.enso +++ b/distribution/std-lib/Standard/src/Base/System/File.enso @@ -9,36 +9,6 @@ polyglot java import java.io.IOException polyglot java import java.nio.file.AccessDeniedException polyglot java import java.nio.file.NoSuchFileException -type File_Error - - ## An error that indicates that the requested file does not exist. - - Arguments: - - file: The file that doesn't exist. - type No_Such_File_Error file - - ## An error that indicates that the program does not have access to the - requested file. - - Arguments: - - file: The file that the program does not have permission to access. - type Access_Denied_Error file - - ## A generic IO error. - - Arguments: - - message: The message for the error. - type Io_Error message - - ## UNSTABLE - - Convert the File error to a human-readable format. - to_display_text : Text - to_display_text = case this of - No_Such_File_Error file -> "The file at " + file.path + " does not exist." - Access_Denied_Error file -> "You do not have permission to access the file at " + file.path + "." - Io_Error msg -> "An IO error has occurred: " + msg.to_text + "." - ## Creates a new file object, pointing to the given path. Arguments: @@ -46,7 +16,11 @@ type File_Error > Example Create a new file pointing to the `data.csv` file in the project directory. - File.new (Enso_Project.data / "data.csv").path + + import Standard.Base.System.File + import Standard.Examples + + example_new = File.new Examples.csv_path new : Text -> File new path = File (Prim_Io.get_file path) @@ -64,7 +38,11 @@ new path = File (Prim_Io.get_file path) > Example Read the `data.csv` file in the project directory's `data` directory. You will need to create the file `data.csv` manually in that directory. - File.read (Enso_Project.data / "data.csv").path + + import Standard.Base.System.File + import Standard.Examples + + example_read = File.read Examples.csv_path read : (Text | File) -> Text read path = .read <| case path of Text -> (here.new path) @@ -74,7 +52,10 @@ read path = .read <| case path of > Example Get the program's current working directory. - File.current_directory + + import Standard.Base.System.File + + example_cwd = File.current_directory current_directory : File current_directory = File (Prim_Io.get_cwd) @@ -82,7 +63,10 @@ current_directory = File (Prim_Io.get_cwd) > Example Get the current user's home directory. - File.home + + import Standard.Base.System.File + + example_home = File.home home : File home = here.new (Prim_Io.get_user_home) @@ -96,6 +80,352 @@ type File - prim_file: The internal representation of the file. type File prim_file + ## Creates a new output stream for this file and runs the specified action + on it. + + Arguments: + - open_options: A vector of `File.Option` objects determining how to open + the stream. These options set the access properties of the stream. + - action: A function that operates on the output stream and returns some + value. The value is returned from this method. + + The created stream is automatically closed when `action` returns (even + if it returns exceptionally). + + > Example + Perform an action on an output stream with the file open for writing. + + import Standard.Base.System.File.Option + import Standard.Examples + + example_with_stream = + file = Examples.scratch_file + action = stream -> stream.write_bytes "hello".utf_8 + file.with_output_stream [Option.Create, Option.Write] action + with_output_stream : Vector.Vector -> (Output_Stream -> Any ! File_Error) -> Any ! File_Error + with_output_stream open_options action = + Resource.bracket (this.new_output_stream open_options) (_.close) action + + ## Creates a new input stream for this file and runs the specified action + on it. + + Arguments: + - open_options: A vector of `File.Option` objects determining how to open + the stream. These options set the access properties of the stream. + - action: A function that operates on the input stream and returns some + value. The value is returned from this method. + + The created stream is automatically closed when `action` returns (even + if it returns exceptionally). + + > Example + Perform an action on an input stream with the file open for reading. + + import Standard.Base.System.File.Option + import Standard.Examples + + example_with_stream = + file = Examples.csv + action = stream -> stream.read_all_bytes + file.with_input_stream [Option.Create, Option.Read] action + with_input_stream : Vector.Vector -> (Input_Stream -> Any ! File_Error) -> Any ! File_Error + with_input_stream open_options action = + Resource.bracket (this.new_input_stream open_options) (_.close) action + + ## Reads all bytes in this file into a byte vector. + + > Example + Read all of the bytes in the file. + + import Standard.Examples + + example_read_bytes = Examples.csv.read_bytes + read_bytes : Vector.Vector ! File_Error + read_bytes = + opts = [Option.Read] + this.with_input_stream opts (_.read_all_bytes) + + ## Reads the whole file into a `Text`, assuming UTF-8 content encoding. + + > Example + Read the contents of the file. + + import Standard.Examples + + example_read = Examples.csv.read + read : Text ! File_Error + read = + bytes = this.read_bytes + Text.from_utf_8 bytes + + ## Appends a number of bytes at the end of this file. + + Arguments: + - contents: A vector of bytes to append to the file. + + > Example + Append the bytes of the text "hello" to a file. + + import Standard.Examples + + example_append_bytes = Examples.scratch_file.append_bytes "hello".utf_8 + append_bytes : Vector.Vector -> Nothing ! File_Error + append_bytes contents = + opts = [Option.Append, Option.Create] + this.with_output_stream opts (_.write_bytes contents) + + ## Appends a UTF-8 encoded `Text` at the end of this file. + + Arguments: + - contents: The UTF-8 encoded text to append to the file. + + > Example + Append the text "hello" to a file. + + import Standard.Examples + + example_append = Examples.scratch_file.append "hello" + append : Text -> Nothing ! File_Error + append contents = this.append_bytes contents.utf_8 + + ## Writes a number of bytes into this file, replacing any existing contents. + + Arguments: + - contents: The vector of bytes to write into the file. + + If the file does not exist, it will be created. + + > Example + Write the bytes of the text "hello" to a file. + + import Standard.Examples + + example_write_bytes = Examples.scratch_file.write_bytes "hello".utf_8 + write_bytes : Vector.Vector -> Nothing ! File_Error + write_bytes contents = + opts = [Option.Write, Option.Create, Option.Truncate_Existing] + this.with_output_stream opts (_.write_bytes contents) + Nothing + + ## Writes a UTF-8 encoded `Text` into this file, replacing any existing + contents. + + Arguments: + - contents: The UTF-8 encoded text to write to the file. + + If the file does not exist, it will be created. + + > Example + Write the text "hello" to a file. + + import Standard.Examples + + example_write = Examples.scratch_file.write "hello" + write : Text -> Nothing ! File_Error + write contents = this.write_bytes contents.utf_8 + + ## Join two path segments together. + + Arguments: + - subpath: The path to join to the path of `this`. + + > Example + Concaatenate two file path segments. + + import Standard.Examples + + example_append = Examples.data_dir / "scratch_file" + / : (Text | File) -> File + / subpath = case subpath of + File prim -> File (this.prim_file.resolve prim) + _ -> File (this.prim_file.resolve subpath) + + ## A text representation of this file. + + > Example + Get a textual representation of a file. + + import Standard.Examples + + example_to_text = Examples.csv.to_text + to_text : Text + to_text = this.prim_file.to_text + + ## A File to JSON conversion. + + > Example + Get a JSON representation of a file. + + import Standard.Examples + + example_to_json = Examples.csv.to_json + to_json : Json.Object + to_json = Json.from_pairs [["type", "File"], ["path", this.path]] + + ## Checks whether the file exists. + + > Example + Check if a file exists. + + import Standard.Examples + + example_exists = Examples.csv.exists + exists : Boolean + exists = this.prim_file.exists + + ## Checks whether the file exists and is a directory. + + > Example + Check if a file is a directory. + + import Standard.Examples + + example_is_directory = Examples.csv.is_directory + is_directory : Boolean + is_directory = this.prim_file.isDirectory + + ## Creates the directory represented by this file if it did not exist. + + It also creates parent directories if they did not exist. + + > Example + Create a directory on the file system. + + import Standard.Examples + + example_is_directory = + (Examples.data_dir / "my_directory") . create_directory + create_directory : Nothing + create_directory = this.prim_file.createDirectories + + ## Checks whether the file exists and is a regular file. + + ? Regular Files + A regular file is one that does not have any special meaning to the + operating system. Examples of files that are not regular are symlinks, + pipes, devices, sockets and directories. + + > Example + Check if a file is regular. + + import Standard.Examples + + example_is_regular_file = Examples.csv.is_regular_file + is_regular_file : Boolean + is_regular_file = this.prim_file.isRegularFile + + ## Resolves the parent filesystem node of this file. + + > Example + Get the parent file of a file. + + import Standard.Examples + + example_parent = Examples.csv.parent + parent : File + parent = File this.prim_file.getParent + + ## Returns the path of this file. + + > Example + Get the path from a file. + + import Standard.Examples + + example_path = Examples.csv.path + path : Text + path = this.prim_file.getPath + + ## Returns the name of this file. + + > Example + Get the name from a file. + + import Standard.Examples + + example_name = Examples.csv.name + name : Text + name = this.prim_file.getName + + ## Converts this file to an equivalent file represented with an absolute + path. + + > Example + Convert a file to an equivalent absolute path. + + import Standard.Examples + + example_absolute = Examples.csv.absolute + absolute : File + absolute = File this.prim_file.getAbsoluteFile + + ## Checks is this file's path is absolute. + + > Example + Check if a file is represented by an absolute path. + + import Standard.Examples + + example_is_absolute = Examples.csv.is_absolute + is_absolute : Boolean + is_absolute = this.prim_file.isAbsolute + + ## Normalizes the filepath. + + > Example + Normalize a file path. + + import Standard.Examples + + example_normalize = Examples.csv.normalize + normalize : File + normalize = File this.prim_file.normalize + + ## Checks if this file has the same `path` as `that`. + + > Example + Check if two files are equivalent. + + import Standard.Examples + + example_eq = Examples.csv == Examples.scratch_file + == : File -> Boolean + == that = this.prim_file.isEqual that.prim_file + + ## Deletes the file. + + If the file is a directory, it must be empty, otherwise a `Panic` will + be thrown. + + > Example + Create a file and then delete it. + + import Standard.Examples + + example_delete = + file = Examples.data_dir / "my_file" + file.write "hello" + file.delete + delete : Nothing ! File_Error + delete = + here.handle_java_exceptions this <| + this.prim_file.delete + Nothing + + ## Deletes the file if it exists on disk. + + If the file is a directory, it must be empty, otherwise a `Panic` will + be thrown. + + > Example + Delete a file if it exists on disk. + + import Standard.Examples + + example_del_if_exists = Examples.scratch_file.delete_if_exists + delete_if_exists : Nothing ! File_Error + delete_if_exists = if this.exists then this.delete else Nothing + ## ADVANCED Returns a new input stream for this file. @@ -132,177 +462,11 @@ type File resource = Managed_Resource.register stream here.close_stream Output_Stream this resource - ## Creates a new output stream for this file and runs the specified action - on it. - - Arguments: - - open_options: A vector of `File.Option` objects determining how to open - the stream. These options set the access properties of the stream. - - action: A function that operates on the output stream and returns some - value. The value is returned from this method. - - The created stream is automatically closed when `action` returns (even - if it returns exceptionally). - with_output_stream : Vector.Vector -> (Output_Stream -> Any ! File_Error) -> Any ! File_Error - with_output_stream open_options action = - Resource.bracket (this.new_output_stream open_options) (_.close) action - - ## Creates a new input stream for this file and runs the specified action - on it. - - Arguments: - - open_options: A vector of `File.Option` objects determining how to open - the stream. These options set the access properties of the stream. - - action: A function that operates on the input stream and returns some - value. The value is returned from this method. - - The created stream is automatically closed when `action` returns (even - if it returns exceptionally). - with_input_stream : Vector.Vector -> (Input_Stream -> Any ! File_Error) -> Any ! File_Error - with_input_stream open_options action = - Resource.bracket (this.new_input_stream open_options) (_.close) action - - ## Reads all bytes in this file into a byte vector. - read_bytes : Vector.Vector ! File_Error - read_bytes = - opts = [Option.Read] - this.with_input_stream opts (_.read_all_bytes) - - ## Reads the whole file into a `Text`, assuming UTF-8 content encoding. - read : Text ! File_Error - read = - bytes = this.read_bytes - Text.from_utf_8 bytes - - ## Appends a number of bytes at the end of this file. - - Arguments: - - contents: A vector of bytes to append to the file. - append_bytes : Vector.Vector -> Nothing ! File_Error - append_bytes contents = - opts = [Option.Append, Option.Create] - this.with_output_stream opts (_.write_bytes contents) - - ## Appends a UTF-8 encoded `Text` at the end of this file. - - Arguments: - - contents: The UTF-8 encoded text to append to the file. - append : Text -> Nothing ! File_Error - append contents = this.append_bytes contents.utf_8 - - ## Writes a number of bytes into this file, replacing any existing contents. - - Arguments: - - contents: The vector of bytes to write into the file. - - If the file does not exist, it will be created. - write_bytes : Vector.Vector -> Nothing ! File_Error - write_bytes contents = - opts = [Option.Write, Option.Create, Option.Truncate_Existing] - this.with_output_stream opts (_.write_bytes contents) - Nothing - - ## Writes a UTF-8 encoded `Text` into this file, replacing any existing - contents. - - Arguments: - - contents: The UTF-8 encoded text to write to the file. - - If the file does not exist, it will be created. - write : Text -> Nothing ! File_Error - write contents = this.write_bytes contents.utf_8 - - ## Join two path segments together. - - Arguments: - - subpath: The path to join to the path of `this`. - / : (Text | File) -> File - / subpath = case subpath of - File prim -> File (this.prim_file.resolve prim) - _ -> File (this.prim_file.resolve subpath) - - ## A text representation of this file. - to_text : Text - to_text = this.prim_file.to_text - - ## A File to JSON conversion. - to_json : Json.Object - to_json = Json.from_pairs [["type", "File"], ["path", this.path]] - - ## Checks whether the file exists. - exists : Boolean - exists = this.prim_file.exists - - ## Checks whether the file exists and is a directory. - is_directory : Boolean - is_directory = this.prim_file.isDirectory - - ## Creates the directory represented by this file if it did not exist. - - It also creates parent directories if they did not exist. - create_directory : Nothing - create_directory = this.prim_file.createDirectories - - ## Checks whether the file exists and is a regular file. - - ? Regular Files - A regular file is one that does not have any special meaning to the - operating system. Examples of files that are not regular are symlinks, - pipes, devices, sockets and directories. - is_regular_file : Boolean - is_regular_file = this.prim_file.isRegularFile - - ## Resolves the parent filesystem node of this file. - parent : File - parent = File this.prim_file.getParent - - ## Returns the path of this file. - path : Text - path = this.prim_file.getPath - - ## Returns the name of this file. - name : Text - name = this.prim_file.getName - - ## Converts this file to an equivalent file represented with an absolute - path. - absolute : File - absolute = File this.prim_file.getAbsoluteFile - - ## Checks is this file's path is absolute. - is_absolute : Boolean - is_absolute = this.prim_file.isAbsolute - - ## Normalizes the filepath. - normalize : File - normalize = File this.prim_file.normalize - - ## Checks if this file has the same `path` as `that`. - == : File -> Boolean - == that = this.prim_file.isEqual that.prim_file - - ## Deletes the file. - - If the file is a directory, it must be empty, otherwise a `Panic` will - be thrown. - delete : Nothing ! File_Error - delete = - here.handle_java_exceptions this <| - this.prim_file.delete - Nothing - - ## Deletes the file if it exists on disk. - - If the file is a directory, it must be empty, otherwise a `Panic` will - be thrown. - delete_if_exists : Nothing ! File_Error - delete_if_exists = if this.exists then this.delete else Nothing - ## An output stream, allowing for interactive writing of contents into an open file. type Output_Stream - ## ADVANCED + ## PRIVATE An output stream, allowing for interactive writing of contents into an open file. @@ -314,10 +478,23 @@ type Output_Stream type Output_Stream file stream_resource ## ADVANCED + Writes a vector of bytes into the file at the current stream position. Arguments: - contents: A vector of bytes to write into the file. + + > Example + Write some bytes through a stream. + + import Standard.Base.System.File.Option + import Standard.Examples + + example_write_bytes = + file = Examples.scratch_file + out_stream = file.new_output_stream [Option.Create, Option.Write] + out_stream.write_bytes "hello".utf_8 + out_stream.close write_bytes : Vector.Vector -> Nothing ! File_Error write_bytes contents = Managed_Resource.with this.stream_resource java_stream-> here.handle_java_exceptions this.file <| @@ -332,6 +509,17 @@ type Output_Stream Even though Streams are closed automatically upon garbage collection, it is still advised to close streams manually if they are not used within a bracket pattern. + + > Example + Open and close a stream. + + import Standard.Base.System.File.Option + import Standard.Examples + + example_write_bytes = + file = Examples.scratch_file + out_stream = file.new_output_stream [Option.Create] + out_stream.close close : Nothing close = Managed_Resource.finalize this.stream_resource @@ -339,7 +527,7 @@ type Output_Stream file. type Input_Stream - ## ADVANCED + ## PRIVATE An input stream, allowing for interactive reading of contents from an open file. @@ -353,6 +541,19 @@ type Input_Stream ## ADVANCED Reads all the bytes in this file into a vector of bytes. + + > Example + Read all of the bytes from a file using a stream. + + import Standard.Base.System.File.Option + import Standard.Examples + + example_read_all = + file = Examples.csv + in_stream = file.new_input_stream [Option.Read] + bytes = in_stream.read_all_bytes + in_stream.close + bytes read_all_bytes : Vector.Vector ! File_Error read_all_bytes = Managed_Resource.with this.stream_resource java_stream-> here.handle_java_exceptions this.file <| @@ -370,6 +571,19 @@ type Input_Stream The length of the returned vector is the same as the number of bytes read. + + > Example + Read 10 of the bytes from a file using a stream. + + import Standard.Base.System.File.Option + import Standard.Examples + + example_read_all = + file = Examples.csv + in_stream = file.new_input_stream [Option.Read] + bytes = in_stream.read_n_bytes 10 + in_stream.close + bytes read_n_bytes : Integer -> Vector.Vector ! File_Error read_n_bytes n = Managed_Resource.with this.stream_resource java_stream-> here.handle_java_exceptions this.file <| @@ -382,6 +596,19 @@ type Input_Stream The returned value is an integer in the range 0-255 representing the next byte of input, or -1 if end of stream is reached. + + > Example + Read byte from a file using a stream. + + import Standard.Base.System.File.Option + import Standard.Examples + + example_read_all = + file = Examples.csv + in_stream = file.new_input_stream [Option.Read] + bytes = in_stream.read_byte + in_stream.close + bytes read_byte : Integer ! File_Error read_byte = Managed_Resource.with this.stream_resource java_stream-> here.handle_java_exceptions this.file <| @@ -394,6 +621,17 @@ type Input_Stream Even though Streams are closed automatically upon garbage collection, it is still advised to close streams manually if they are not used within a bracket pattern. + + > Example + Open and close a stream. + + import Standard.Base.System.File.Option + import Standard.Examples + + example_read_all = + file = Examples.csv + in_stream = file.new_input_stream [Option.Read] + in_stream.close close : Nothing close = Managed_Resource.finalize this.stream_resource @@ -445,3 +683,34 @@ close_stream : Any -> Nothing close_stream stream = stream.close Nothing + +type File_Error + + ## An error that indicates that the requested file does not exist. + + Arguments: + - file: The file that doesn't exist. + type No_Such_File_Error file + + ## An error that indicates that the program does not have access to the + requested file. + + Arguments: + - file: The file that the program does not have permission to access. + type Access_Denied_Error file + + ## A generic IO error. + + Arguments: + - message: The message for the error. + type Io_Error message + + ## UNSTABLE + + Convert the File error to a human-readable format. + to_display_text : Text + to_display_text = case this of + No_Such_File_Error file -> "The file at " + file.path + " does not exist." + Access_Denied_Error file -> "You do not have permission to access the file at " + file.path + "." + Io_Error msg -> "An IO error has occurred: " + msg.to_text + "." + diff --git a/distribution/std-lib/Standard/src/Base/System/Platform.enso b/distribution/std-lib/Standard/src/Base/System/Platform.enso index aeb03fad3f3..501c5524472 100644 --- a/distribution/std-lib/Standard/src/Base/System/Platform.enso +++ b/distribution/std-lib/Standard/src/Base/System/Platform.enso @@ -21,7 +21,10 @@ type Os > Example Return the OS type: - Platform.os + + import Standard.Base.System.Platform + + example_os = Platform.os os : Os os = here.from_text System.os diff --git a/distribution/std-lib/Standard/src/Base/System/Process.enso b/distribution/std-lib/Standard/src/Base/System/Process.enso index b098edff351..cffd342f7be 100644 --- a/distribution/std-lib/Standard/src/Base/System/Process.enso +++ b/distribution/std-lib/Standard/src/Base/System/Process.enso @@ -1,3 +1,5 @@ +from Standard.Base import all + import Standard.Base.System.Process.Exit_Code from Standard.Base.Data.Vector import Vector @@ -7,22 +9,46 @@ from Builtins import Array, System, True, False Call a command with a list of arguments. + Arguments: + - command: The command to execute. + - arguments: The arguments to pass to `command`. + > Example - Call the `echo` command with arguments - Process.run "echo" ["-n", "Hello!"] - The result is printed to stdout: - Hello! + Call the "echo" command. + + import Standard.Base.System.Platform + import Standard.Base.System.Process + + example_run = case Platform.os of + Platform.Windows -> Process.run "PowerShell" ["-Command", "exit 42"] + _ -> Process.run "bash" ["-c", "exit 42"] run : Text -> Vector.Vector Text -> Exit_Code run command arguments=[] = result = System.create_process command arguments.to_array input="" redirect_in=True redirect_out=True redirect_err=True Exit_Code.from_number result.exit_code +## Create a new process builder. + + Arguments: + - command: The command to execute on the system. + - arguments: The arguments to pass to `command`. These must be text. + - stdin: Any content to pass to the standard input for `command`. + + > Example + Create a new builder for a command "echo". + + import Standard.Base.System.Process + + example_new_builder = Process.new_builder "echo" +new_builder : Text -> Vector Text -> Text -> Builder +new_builder command arguments=[] stdin="" = Builder command arguments stdin + ## UNSTABLE The builder object that is used to create operating system processes. type Builder - ## UNSTABLE + ## PRIVATE A builder object that is used to create operating system processes. @@ -35,7 +61,7 @@ type Builder We recommend that you use this type with its builder interface. Start by creating a `Builder "command"` and then call functions on it to set arguments and standard output. It results in much clearer code. - type Builder command arguments=[] stdin="" + type Builder command arguments stdin ## UNSTABLE @@ -43,6 +69,15 @@ type Builder Arguments: - arguments: The arguments to pass to the process. + + > Examples + Set the arguments to the process using a builder. + + import Standard.Base.System.Process + + example_set_args = + builder = Process.new_builder "echo" + builder.set_arguments ["hello, world!"] set_arguments : Vector.Vector Text -> Builder set_arguments arguments = Builder this.command arguments this.stdin @@ -53,6 +88,15 @@ type Builder Arguments: - stdin: The standard input contents to pass to the process. + + > Examples + Set the standard input to a process using a builder. + + import Standard.Base.System.Process + + example_set_args = + builder = Process.new_builder "echo" + builder.set_stdin "hello, world!" set_stdin : Text -> Builder set_stdin stdin = Builder this.command this.arguments stdin @@ -61,11 +105,14 @@ type Builder Create a process using a builder returning the result of execution. > Example - Create a script redirecting the input to stdout: - builder = Process.builder "bash" ["-c", "read line; echo -n $line"] "test" - builder.create - The result is: - Process_Result Exit_Success "test" "" + Execute the process contained in the builder. + + import Standard.Base.System.Process + + example_create = + builder = Process.new_builder "echo" + with_args = builder.set_arguments ["hello, world!"] + with_args.create create : Result create = result = System.create_process this.command this.arguments.to_array this.stdin redirect_in=False redirect_out=False redirect_err=False diff --git a/distribution/std-lib/Standard/src/Base/System/Process/Exit_Code.enso b/distribution/std-lib/Standard/src/Base/System/Process/Exit_Code.enso index d5fdf79c5c6..843a48720ee 100644 --- a/distribution/std-lib/Standard/src/Base/System/Process/Exit_Code.enso +++ b/distribution/std-lib/Standard/src/Base/System/Process/Exit_Code.enso @@ -16,7 +16,10 @@ type Exit_Code > Example Convert a success code to a corresponding number. - Exit_Success.to_number + + import Standard.Base.System.Process.Exit_Code + + example_to_number = Exit_Code.Exit_Success.to_number to_number : Integer to_number = case this of Exit_Success -> 0 @@ -29,6 +32,9 @@ type Exit_Code > Example Create a failure exit code. - Exit_Code.from_number 1 + + import Standard.Base.System.Process.Exit_Code + + example_from_number = Exit_Code.from_number 1 from_number : Number -> Exit_Code from_number code = if code == 0 then Exit_Success else Exit_Failure code diff --git a/distribution/std-lib/Standard/src/Examples.enso b/distribution/std-lib/Standard/src/Examples.enso index b82ae92d0be..55cf73d13b3 100644 --- a/distribution/std-lib/Standard/src/Examples.enso +++ b/distribution/std-lib/Standard/src/Examples.enso @@ -1,12 +1,15 @@ from Standard.Base import all import Standard.Base.Data.Time +import Standard.Base.Network.Http +import Standard.Base.System.Platform # Renamed to avoid clashing with an uppercase name resolution for `duration`. import Standard.Base.Data.Json as Enso_Json import Standard.Base.Data.List as Enso_List import Standard.Base.Data.Map as Enso_Map import Standard.Base.Data.Time.Duration as Enso_Duration +import Standard.Base.Network.Uri as Enso_Uri # Can do the top-level examples directory. @@ -33,10 +36,25 @@ import Standard.Base.Data.Time.Duration as Enso_Duration - message: The message contained in the error type. type Example_Error_Type message +## The standard library data directory. +data_dir : File +data_dir = Enso_Project.data + ## An example CSV file for experimenting with Table and its APIs. csv : File csv = Enso_Project.data / "food_shop_inventory.csv" +## The path to the CSV. +csv_path : Text +csv_path = here.csv.path + +## A file that is used for writing temporary data as part of tests. +scratch_file : File +scratch_file = + file = Enso_Project.data / "scratch_file" + if file.exists then file.delete else Nothing + file + ## An example duration for experimenting with duration APIs. duration : Duration duration = Enso_Duration.between (Time.new 2020 10 20) Time.now @@ -84,3 +102,49 @@ list = Cons 1 (Cons 2 (Cons 3 Nil)) map : Enso_Map.Map map = Enso_Map.empty . insert 1 "one" . insert 3 "three" . insert 5 "five" +## A dummy type that is used for example purposes. +type No_Methods + +## Returns a no_such_method_error as a value. +no_such_method : No_Such_Method_Error +no_such_method = Panic.recover No_Methods.frobnicate . catch + +## A simple error type for example purposes. +type My_Error message + +## Throws an error. +throw_error : Nothing ! My_Error +throw_error = Error.throw <| My_Error "Example error." + +## Throws a panic. +throw_panic : Nothing +throw_panic = Panic.throw <| My_Error "Example panic." + +## A URL for open-source geographic data about the locations of bus-stop ads in + Los Angeles. +geo_data_url : Text +geo_data_url = "https://opendata.arcgis.com/datasets/0f77c86999a440178f2be3650d00f7f6_2.geojson" + +## Gets an HTTP response from a network endpoint. + + ! Makes a Network Request + Calling this method will cause Enso to make a network request to a data + endpoint. +get_response : Http.Response +get_response = Http.get here.geo_data_url + +## Gets HTTP data from a network endpoint. + + ! Makes a Network Request + Calling this method will cause Enso to make a network request to a data + endpoint. +get_geo_data : Http.Response.Body +get_geo_data = Http.fetch here.geo_data_url + +## A simple HTTP client for examples. +http_client : Http +http_client = Http.new (timeout = 30.seconds) + +## A basic URI for examples. +uri : Uri +uri = Enso_Uri.parse "http://user:pass@example.com/foo/bar?key=val" diff --git a/engine/runtime/src/main/resources/Builtins.enso b/engine/runtime/src/main/resources/Builtins.enso index f4ab1ceda5d..ef96f9c7932 100644 --- a/engine/runtime/src/main/resources/Builtins.enso +++ b/engine/runtime/src/main/resources/Builtins.enso @@ -21,6 +21,7 @@ type Boolean > Example Comparing True to False to get False. + True == False == : Boolean -> Boolean == that = @Builtin_Method "Boolean.==" @@ -37,6 +38,7 @@ type Boolean > Example Computing the conjunction of False and True (to get False). + False && True && : Boolean -> Boolean && that = @Builtin_Method "Boolean.&&" @@ -53,6 +55,7 @@ type Boolean > Example Computing the disjunction of True and False (to get True). + True || False || : Boolean -> Boolean || that = @Builtin_Method "Boolean.||" @@ -60,7 +63,8 @@ type Boolean ## Computes the logical negation of this. > Example - Negating True to get False + Negating True to get False. + True.not not : Boolean not = @Builtin_Method "Boolean.not" @@ -69,6 +73,7 @@ type Boolean > Example Converting the value True to text. + True.to_text to_text : Text to_text = @Builtin_Method "Boolean.to_text" @@ -85,6 +90,7 @@ type Boolean > Example Telling the user if a number 27 is divisible by three. + if (27 % 3) == 0 then IO.println "Yes" else IO.println "No" if_then_else : Any -> Any -> Any if_then_else ~on_true ~on_false = @Builtin_Method "Boolean.if_then_else" @@ -100,6 +106,7 @@ type Boolean > Example Printing a message to the user only if a number is divisible by three. + if (27 % 3) == 0 then IO.println "Fizz" if_then : Any -> Any | Nothing if_then ~on_true = @Builtin_Method "Boolean.if_then" @@ -129,6 +136,7 @@ type Debug > Example Dropping into a debugging REPL during execution. + Debug.breakpoint breakpoint : Nothing breakpoint = @Builtin_Method "Debug.breakpoint" @@ -145,6 +153,7 @@ type Debug > Example Evaluating the expression 1 + 1 and assigning it to a value. + result = Debug.eval "1 + 1" eval : Text -> Any eval expression = @Builtin_Method "Debug.eval" @@ -166,10 +175,6 @@ type Any Arguments: - handler: The function to call on this if it is an error value. - - > Example - Catching an erroneous value to perform some operation on it. - (Time.Time_Error "Message").catch_primitive (err -> IO.println err) catch_primitive : (Error -> Any) -> Any catch_primitive handler = @Builtin_Method "Any.catch" @@ -178,6 +183,7 @@ type Any > Example Getting a textual representation of the number 7. + 7.to_text to_text : Text to_text = @Builtin_Method "Any.to_text" @@ -206,6 +212,7 @@ type Error > Example Throw a dataflow error containing the text "Oops". + Error.throw "Oops" throw : Any -> Error throw payload = @Builtin_Method "Error.throw" @@ -217,10 +224,6 @@ type Error Arguments: - handler: The function to call on this if it is an error value. - - > Example - Catching an erroneous value to perform some operation on it. - (Time.Time_Error "Message").catch_primitive (err -> IO.println err) catch_primitive : (Error -> Any) -> Any catch_primitive handler = @Builtin_Method "Any.catch" @@ -235,6 +238,7 @@ type Error > Example Converting a thrown error to text. + Error.throw "foo" . to_text to_text : Text to_text = @Builtin_Method "Error.to_text" @@ -353,6 +357,7 @@ type Panic > Example Throwing a panic containing the text "Oh no!". + Panic.throw "Oh no!" throw : Any -> Panic throw payload = @Builtin_Method "Panic.throw" @@ -369,6 +374,7 @@ type Panic > Example Handling a panic for a panicking action. + Panic.recover (Panic.throw "Oh no!") recover : Any -> Any recover ~action = @Builtin_Method "Panic.catch" @@ -393,8 +399,10 @@ type Function > Example Evaluate a fully applied function to get 4. - f (a = 2) = a * a - f.call + + example_call = + f (a = 2) = a * a + f.call call : Any call = @Builtin_Method "Function.call" @@ -442,6 +450,7 @@ type Polyglot > Example Get a list of the fields for an object o. + Polyglot.get_members o get_members : Any -> Array get_members object = @Builtin_Method "Polyglot.get_members" @@ -455,6 +464,7 @@ type Polyglot > Example Instantiate a new Java Integer with the value 1. + Polyglot.new Integer [1] new : Any -> Vector -> Any new constructor arguments = @Builtin_Method "Polglot.new" @@ -484,6 +494,7 @@ type Java > Example Adding Random to the classpath. + Java.add_to_class_path "java.util.Random" add_to_class_path : Text -> Nothing add_to_class_path path = @Builtin_Method "Java.add_to_class_path" @@ -498,6 +509,7 @@ type Java > Example Look up java's Random class. + Java.lookup_class "java.util.Random" lookup_class : Text -> Any lookup_class name = @Builtin_Method "Java.lookup_class" @@ -546,6 +558,7 @@ type IO > Example Print the message "Oh no!" to standard error. + IO.print_err "Oh no!" print_err : Any -> Nothing print_err message = @Builtin_Method "IO.print_err" @@ -558,6 +571,7 @@ type IO > Example Print the message "Oh yes!" to standard output. + IO.println "Oh yes!" println : Any -> Nothing println message = @Builtin_Method "IO.println" @@ -565,8 +579,9 @@ type IO ## Reads a line from standard input. > Example - Read a line from standard input into a variable. - input = IO.readln + Read a line from standard input. + + IO.readln readln : Text readln = @Builtin_Method "IO.readln" @@ -765,6 +780,7 @@ type Array > Example Create an empty array. + Array.empty empty : Array empty = @Builtin_Method "Array.empty" @@ -776,6 +792,7 @@ type Array > Example Create a new array of size 10. + Array.new 10 new : Integer -> Array new size = @Builtin_Method "Array.new" @@ -846,8 +863,8 @@ type Array > Example Copying elements from one array to another. - Array.copy [1,2,3].to_array 0 (Vector.fill 3 0).to_array 0 3 + Array.copy [1,2,3].to_array 0 (Vector.fill 3 0).to_array 0 3 copy : Array -> Integer -> Array -> Integer -> Integer -> Nothing copy src source_index dest dest_index count = @Builtin_Method "Array.copy" @@ -859,6 +876,7 @@ type Array > Example Get the element at index 1. + [1,2,3].to_array.at 1 at : Integer -> Any at index = @Builtin_Method "Array.at" @@ -883,6 +901,7 @@ type Array > Example Getting the length of an array. + [1,2,3].to_array.length length : Integer length = @Builtin_Method "Array.length" @@ -896,6 +915,7 @@ type Array > Example Sorting an array of numbers. + [1,2,3].to_array.sort sort : (Any -> Any -> Ordering) -> Nothing sort comparator = @Builtin_Method "Array.sort" @@ -921,6 +941,7 @@ type Ref > Example Creating a new reference containing the value 7. + Ref.new 7 new : Any -> Ref new value = @Builtin_Method "Ref.new" @@ -932,6 +953,7 @@ type Ref > Example Getting the contents of a reference. + Ref.get (Ref.new 0) get : Ref -> Any get ref = @Builtin_Method "Ref.get" @@ -944,6 +966,7 @@ type Ref > Example Storing the value 10 in a reference. + Ref.put (Ref.new 0) 7 put : Ref -> Any -> Any put ref new_value = @Builtin_Method "Ref.put" @@ -984,6 +1007,7 @@ type Integer > Example Adding 10 and 15. + 10 + 15 + : Number -> Number + that = @Builtin_Method "Integer.+" @@ -995,6 +1019,7 @@ type Integer > Example Subtract 5 from 2. + 2 - 5 - : Number -> Number - that = @Builtin_Method "Integer.-" @@ -1009,6 +1034,7 @@ type Integer > Example Multiplying 3 by 5. + 3 * 5 * : Number -> Number * that = @Builtin_Method "Integer.*" @@ -1023,6 +1049,7 @@ type Integer > Example Dividing 10 by 4 to get 2.5. + 10 / 4 / : Number -> Number / that = @Builtin_Method "Integer./" @@ -1039,6 +1066,7 @@ type Integer > Example Computing the remainder when dividing 10 by 3 (which is 1). + 10 % 3 % : Number -> Number ! Arithmetic_Error % that = @Builtin_Method "Integer.%" @@ -1050,6 +1078,7 @@ type Integer > Example Computing 2 cubed. + 2^3 ^ : Number -> Number ^ that = @Builtin_Method "Integer.^" @@ -1061,6 +1090,7 @@ type Integer > Example Comparing 7 and 2 for equality. + 7 == 2 == : Number -> Boolean == that = @Builtin_Method "Integer.==" @@ -1072,6 +1102,7 @@ type Integer > Example Checking if 10 is greater than 7. + 10 > 7 > : Number -> Boolean > that = @Builtin_Method "Integer.>" @@ -1083,6 +1114,7 @@ type Integer > Example Checking if 10 is greater than or equal to 7. + 10 >= 7 >= : Number -> Boolean >= that = @Builtin_Method "Integer.>=" @@ -1094,6 +1126,7 @@ type Integer > Example Checking if 10 is less than 7. + 10 < 7 < : Number -> Boolean < that = @Builtin_Method "Integer.<" @@ -1105,6 +1138,7 @@ type Integer > Example Checking if 10 is less than or equal to 7. + 10 <= 7 <= : Number -> Boolean <= that = @Builtin_Method "Integer.<=" @@ -1116,6 +1150,7 @@ type Integer > Example Computing the absolute value of -10. + -10.abs abs : Integer abs = @Builtin_Method "Integer.abs" @@ -1127,6 +1162,7 @@ type Integer > Example Computing the ceiling of 4. + 4.ceil ceil : Integer ceil = @Builtin_Method "Integer.ceil" @@ -1139,6 +1175,7 @@ type Integer > Example Computing the ordering of 1 and 4 (Less). + 1.compare_to 4 compare_to : Number -> Ordering compare_to that = @Builtin_Method "Integer.compare_to" @@ -1154,6 +1191,7 @@ type Integer > Example Dividing 10 by 3 to get 3. + 10.div 3 div : Integer -> Number ! Arithmetic_Error div that = @Builtin_Method "Integer.div" @@ -1165,6 +1203,7 @@ type Integer > Example Computing the floor of 4. + 4.floor floor : Integer floor = @Builtin_Method "Integer.floor" @@ -1173,6 +1212,7 @@ type Integer > Example Negate 5 to get -5. + 5.negate negate : Integer negate = @Builtin_Method "Integer.negate" @@ -1181,6 +1221,7 @@ type Integer > Example Convert 5 to a decimal to get 5.0. + 5.to_decimal to_decimal : Decimal to_decimal = @Builtin_Method "Integer.to_decimal" @@ -1196,6 +1237,7 @@ type Integer ? Example Computing the bitwise conjunction of 2_01101101 and 2_11110000. + 2_01101101.bit_and 2_11110000 bit_and : Integer -> Integer bit_and that = @Builtin_Method "Integer.bit_and" @@ -1206,6 +1248,7 @@ type Integer ? Example Bitwise negation of 2_0110. + 2_0110.bit_not bit_not : Integer bit_not = @Builtin_Method "Integer.bit_not" @@ -1221,6 +1264,7 @@ type Integer > Example Computing the bitwise disjunction of 2_01101101 and 2_11110000. + 2_01101101.bit_or 2_11110000 bit_or : Integer -> Integer bit_or that = @Builtin_Method "Integer.bit_or" @@ -1235,6 +1279,7 @@ type Integer > Example Computing the bitwise exclusive or of 2_01101101 and 2_11110000. + 2_01101101.bit_xor 2_11110000 bit_xor : Integer -> Integer bit_xor that = @Builtin_Method "Integer.bit_xor" @@ -1253,6 +1298,7 @@ type Integer > Example Shift the bits of the number 1 left by four bits. + 1.bit_shift 4 bit_shift : Integer -> Integer ! Arithmetic_Error bit_shift that = @Builtin_Method "Integer.bit_shift" @@ -1271,6 +1317,7 @@ type Integer > Example Shift the bits of the number 1 left by four bits. + 1.bit_shift_l 4 bit_shift_l : Integer -> Integer ! Arithmetic_Error bit_shift_l that = @Builtin_Method "Integer.bit_shift_l" @@ -1289,6 +1336,7 @@ type Integer > Example Shift the bits of the number 1 right by four bits. + 1.bit_shift_r 4 bit_shift_r : Integer -> Integer ! Arithmetic_Error bit_shift_r that = @Builtin_Method "Integer.bpit_shift_r" @@ -1314,6 +1362,7 @@ type Decimal > Example Adding 10.1 and 15. + 10.1 + 15 + : Number -> Number + that = @Builtin_Method "Decimal.+" @@ -1325,6 +1374,7 @@ type Decimal > Example Subtract 5 from 2.78. + 2.78 - 5 - : Number -> Number - that = @Builtin_Method "Decimal.-" @@ -1339,6 +1389,7 @@ type Decimal > Example Multiplying 3 by 5.27. + 5.27 * 3 * : Number -> Number * that = @Builtin_Method "Decimal.*" @@ -1353,6 +1404,7 @@ type Decimal > Example Dividing 10 by 4.5. + 10 / 4.5 / : Number -> Number / that = @Builtin_Method "Decimal./" @@ -1364,6 +1416,7 @@ type Decimal > Example Computing 2.2 cubed. + 2.2^3 ^ : Number -> Number ^ that = @Builtin_Method "Decimal.^" @@ -1375,6 +1428,7 @@ type Decimal > Example Comparing 7 and 2.1 for equality. + 7 == 2.1 == : Number -> Boolean == that = @Builtin_Method "Decimal.==" @@ -1386,6 +1440,7 @@ type Decimal > Example Checking if 10 is greater than 7.3. + 10 > 7.3 > : Number -> Boolean > that = @Builtin_Method "Decimal.>" @@ -1397,6 +1452,7 @@ type Decimal > Example Checking if 10 is greater than or equal to 7.3. + 10 >= 7.3 >= : Number -> Boolean >= that = @Builtin_Method "Decimal.>=" @@ -1408,6 +1464,7 @@ type Decimal > Example Checking if 10 is less than 7.3. + 10 < 7.3 < : Number -> Boolean < that = @Builtin_Method "Decimal.<" @@ -1419,6 +1476,7 @@ type Decimal > Example Checking if 10.4 is less than or equal to 7. + 10.4 <= 7 <= : Number -> Boolean <= that = @Builtin_Method "Decimal.<=" @@ -1430,6 +1488,7 @@ type Decimal > Example Computing the absolute value of -10.63. + -10.63.abs abs : Decimal abs = @Builtin_Method "Decimal.abs" @@ -1440,6 +1499,7 @@ type Decimal > Example Computing the ceiling of 4.736 (which is 5). + 4.736.ceil ceil : Integer ceil = @Builtin_Method "Integer.ceil" @@ -1452,6 +1512,7 @@ type Decimal > Example Computing the ordering of 1.732 and 4 (Less). + 1.732.compare_to 4 compare_to : Number -> Ordering compare_to that = @Builtin_Method "Decimal.compare_to" @@ -1462,6 +1523,7 @@ type Decimal > Example Computing the floor of 4.323 (which is 4). + 4.323.floor floor : Integer floor = @Builtin_Method "Decimal.floor" @@ -1470,6 +1532,7 @@ type Decimal > Example Negate 5.1 to get -5.1. + 5.1.negate negate : Decimal negate = @Builtin_Method "Decimal.negate" @@ -1481,6 +1544,7 @@ type Decimal > Example Convert 5.0 to a decimal to get 5.0. + 5.0.to_decimal to_decimal : Decimal to_decimal = @Builtin_Method "Decimal.to_decimal" @@ -1530,10 +1594,6 @@ type Managed_Resource - resource: The resource to be managed automatically. - function: The action to be executed on resource to clean it up when it is no longer in use. - - > Example - Registering a managed resource. - Managed_Resource register : Any -> (Any -> Nothing) -> Managed_Resource register resource function = @Builtin_Method "Managed_Resource.register" @@ -1588,6 +1648,7 @@ type Runtime > Example Ask for the runtime to collect garbage. + Runtime.gc gc : Nothing gc = @Builtin_Method "Runtime.gc" @@ -1605,6 +1666,7 @@ type Runtime > Example Print something to the console without it being inlined. + Runtime.no_inline <| IO.println "Hi!" no_inline : Any -> Any no_inline ~action = @Builtin_Method "Runtime.no_inline" @@ -1623,6 +1685,7 @@ type Runtime > Example Print something to the console without it being inlined. + Runtime.no_inline_with_arg IO.println "Hi!" no_inline_with_arg : Any -> Any no_inline_with_arg function arg = @Builtin_Method "Runtime.no_inline_with_arg" @@ -1646,6 +1709,7 @@ type State > Example Print a value from the state. + State.run Integer 0 <| IO.println (State.get Integer) run : Any -> Any -> Any -> Any run key local_state ~computation = @Builtin_Method "State.run" @@ -1661,6 +1725,7 @@ type State > Example Get the value of state for a key. + State.get Decimal get : Any -> Any ! Uninitialized_State get key = @Builtin_Method "State.get" @@ -1677,6 +1742,7 @@ type State > Example Store a new value in the state for a given key. + State.put Text 2821 put : Any -> Any -> Any ! Uninitialized_State put key new_state = @Builtin_Method "State.put" @@ -1710,6 +1776,7 @@ type System > Example Exit the enso program with a failure. + System.exit 42 exit : Integer -> Nothing exit code = @Builtin_Method "System.exit" @@ -1718,7 +1785,8 @@ type System > Example Getting the current value of the nanosecond timer. - current_time = System.nano_time + + System.nano_time nano_time : Integer nano_time = @Builtin_Method "System.nano_time" @@ -1760,6 +1828,7 @@ type Text > Example Concatenating two texts. + "Hello" + ", world!" + : Text -> Text + that = @Builtin_Method "Text.+" @@ -1798,6 +1867,7 @@ type Thread > Example Die on thread interrupts. + Thread.with_interrupt_handler (1 + 1) <| IO.println "I died!" with_interrupt_handler : Any -> Any -> Any with_interrupt_handler ~action ~interrupt_handler = diff --git a/test/Tests/src/Network/Http_Spec.enso b/test/Tests/src/Network/Http_Spec.enso index cd250af47d7..1901273438d 100644 --- a/test/Tests/src/Network/Http_Spec.enso +++ b/test/Tests/src/Network/Http_Spec.enso @@ -80,6 +80,10 @@ spec = res.to_json.should_equal expected_response Test.specify "should return error if the fetch method fails" <| Http.fetch "http://undefined_host" . should_fail_with Http.Request_Error + Test.specify "should send Head request" <| + res = Http.new.head "http://localhost:8080/get" + res.code.should_equal Status_Code.ok + res.body.to_text.should_equal '' Test.specify "should Post empty body" <| expected_response = Json.parse <| ''' { @@ -234,3 +238,23 @@ spec = res = Http.post_json "http://localhost:8080/post" json res.code.should_equal Status_Code.ok res.body.to_json.should_equal expected_response + Test.specify "should Post binary" <| + expected_response = Json.parse <| ''' + { + "headers": { + "Content-Length": "12", + "Content-Type": "application/octet-stream", + "User-Agent": "Java-http-client/11.0.10" + }, + "origin": "127.0.0.1", + "url": "", + "args": {}, + "data": "Hello World!", + "files": null, + "form": null, + "json": null + } + body_bytes = Request_Body.Bytes "Hello World!".utf_8 + res = Http.new.post "http://localhost:8080/post" body_bytes + res.code.should_equal Status_Code.ok + res.body.to_json.should_equal expected_response diff --git a/test/Tests/src/System/Process_Spec.enso b/test/Tests/src/System/Process_Spec.enso index 0514c08f120..5a2a5bca2d7 100644 --- a/test/Tests/src/System/Process_Spec.enso +++ b/test/Tests/src/System/Process_Spec.enso @@ -25,19 +25,19 @@ spec = Test.group "Process" <| Test.specify "should return stdout" <| case Platform.os of Platform.Linux -> - builder = Process.builder "bash" ["-c", "echo -n Hello"] + builder = Process.new_builder "bash" ["-c", "echo -n Hello"] result = builder.create result.exit_code.to_number . should_equal 0 result.stdout . should_equal "Hello" result.stderr . should_equal "" Platform.MacOS -> - builder = Process.builder "bash" ["-c", "echo -n Hello"] + builder = Process.new_builder "bash" ["-c", "echo -n Hello"] result = builder.create result.exit_code.to_number . should_equal 0 result.stdout . should_equal "Hello" result.stderr . should_equal "" Platform.Windows -> - builder = Process.builder "PowerShell" ["-Command", "[System.Console]::Out.Write('Hello')"] + builder = Process.new_builder "PowerShell" ["-Command", "[System.Console]::Out.Write('Hello')"] result = builder.create result.exit_code.to_number . should_equal 0 result.stdout . should_equal "Hello" @@ -47,19 +47,19 @@ spec = Test.group "Process" <| Test.specify "should return stderr" <| case Platform.os of Platform.Linux -> - builder = Process.builder "bash" ["-c", "echo -n Error 1>&2"] + builder = Process.new_builder "bash" ["-c", "echo -n Error 1>&2"] result = builder.create result.exit_code.to_number . should_equal 0 result.stdout . should_equal "" result.stderr . should_equal "Error" Platform.MacOS -> - builder = Process.builder "bash" ["-c", "echo -n Error 1>&2"] "" + builder = Process.new_builder "bash" ["-c", "echo -n Error 1>&2"] "" result = builder.create result.exit_code.to_number . should_equal 0 result.stdout . should_equal "" result.stderr . should_equal "Error" Platform.Windows -> - builder = Process.builder "PowerShell" ["-Command", "[System.Console]::Error.Write('Error')"] "" + builder = Process.new_builder "PowerShell" ["-Command", "[System.Console]::Error.Write('Error')"] "" result = builder.create result.exit_code.to_number . should_equal 0 result.stdout . should_equal "" @@ -69,19 +69,19 @@ spec = Test.group "Process" <| Test.specify "should feed stdin" <| case Platform.os of Platform.Linux -> - builder = Process.builder "bash" ["-c", "read line; echo -n $line"] . set_stdin "sample" + builder = Process.new_builder "bash" ["-c", "read line; echo -n $line"] . set_stdin "sample" result = builder.create result.exit_code.to_number . should_equal 0 result.stdout . should_equal "sample" result.stderr . should_equal "" Platform.MacOS -> - builder = Process.builder "bash" ["-c", "read line; echo -n $line"] . set_stdin "sample" + builder = Process.new_builder "bash" ["-c", "read line; echo -n $line"] . set_stdin "sample" result = builder.create result.exit_code.to_number . should_equal 0 result.stdout . should_equal "sample" result.stderr . should_equal "" Platform.Windows -> - builder = Process.builder "PowerShell" ["-Command", "[System.Console]::ReadLine()"] . set_stdin "sample" + builder = Process.new_builder "PowerShell" ["-Command", "[System.Console]::ReadLine()"] . set_stdin "sample" result = builder.create result.exit_code.to_number . should_equal 0 result.stdout . should_equal 'sample\r\n'