From 18e4b1eed55acacea6421b010a6b23752607014f Mon Sep 17 00:00:00 2001 From: "Sean T. Allen" Date: Fri, 21 Aug 2026 19:29:01 -0400 Subject: [PATCH] Turn on pony-lint Closes #145 --- .../breakage-against-ponyc-latest.yml | 27 +- .github/workflows/pony-lint.yml | 24 + .release-notes/next-release.md | 48 +- AGENTS.md | 3 +- CHANGELOG.md | 3 +- Makefile | 9 +- README.md | 6 +- examples/create-gist-oo/create_gist_oo.pony | 4 + examples/create-gist-oo/main.pony | 66 +- examples/create-gist/create_gist.pony | 3 + examples/create-gist/main.pony | 66 +- .../create_issue_comment_oo.pony | 4 + examples/create-issue-comment-oo/main.pony | 78 +- .../create_issue_comment.pony | 4 + examples/create-issue-comment/main.pony | 52 +- examples/create-label-oo/create_label_oo.pony | 4 + examples/create-label-oo/main.pony | 62 +- examples/create-label/create_label.pony | 4 + examples/create-label/main.pony | 50 +- .../create-release-oo/create_release_oo.pony | 4 + examples/create-release-oo/main.pony | 58 +- examples/create-release/create_release.pony | 4 + examples/create-release/main.pony | 47 +- examples/delete-label-oo/delete_label_oo.pony | 4 + examples/delete-label-oo/main.pony | 72 +- examples/delete-label/delete_label.pony | 4 + examples/delete-label/main.pony | 58 +- examples/get-commit-oo/get_commit_oo.pony | 4 + examples/get-commit-oo/main.pony | 67 +- examples/get-commit/get_commit.pony | 3 + examples/get-commit/main.pony | 53 +- examples/get-gist-oo/get_gist_oo.pony | 4 + examples/get-gist-oo/main.pony | 44 +- examples/get-gist/get_gist.pony | 4 + examples/get-gist/main.pony | 44 +- .../get_issue_comments_oo.pony | 4 + examples/get-issue-comments-oo/main.pony | 83 +- .../get_issue_comments.pony | 4 + examples/get-issue-comments/main.pony | 59 +- examples/get-issue-oo/get_issue_oo.pony | 4 + examples/get-issue-oo/main.pony | 64 +- examples/get-issue/get_issue.pony | 4 + examples/get-issue/main.pony | 48 +- examples/get-issues-oo/get_issues_oo.pony | 4 + examples/get-issues-oo/main.pony | 159 ++-- examples/get-issues/get_issues.pony | 4 + examples/get-issues/main.pony | 149 ++-- .../get_pull_request_files_oo.pony | 4 + examples/get-pull-request-files-oo/main.pony | 88 +- .../get_pull_request_files.pony | 4 + examples/get-pull-request-files/main.pony | 62 +- .../get_pull_request_oo.pony | 4 + examples/get-pull-request-oo/main.pony | 68 +- .../get-pull-request/get_pull_request.pony | 4 + examples/get-pull-request/main.pony | 51 +- .../get_repository_labels.pony | 3 + examples/get-repository-labels/main.pony | 58 +- .../get-repository-oo/get_repository_oo.pony | 4 + examples/get-repository-oo/main.pony | 43 +- examples/get-repository/get_repository.pony | 3 + examples/get-repository/main.pony | 43 +- .../gist-comments-oo/gist_comments_oo.pony | 4 + examples/gist-comments-oo/main.pony | 68 +- examples/gist-comments/gist_comments.pony | 3 + examples/gist-comments/main.pony | 52 +- examples/list-gists-oo/list_gists_oo.pony | 4 + examples/list-gists-oo/main.pony | 55 +- examples/list-gists/list_gists.pony | 3 + examples/list-gists/main.pony | 55 +- examples/search-issues/main.pony | 60 +- examples/search-issues/search_issues.pony | 4 + examples/standard-pony-labels/main.pony | 180 ++-- .../standard_pony_labels.pony | 4 + examples/star-gist-oo/main.pony | 70 +- examples/star-gist-oo/star_gist_oo.pony | 4 + examples/star-gist/main.pony | 53 +- examples/star-gist/star_gist.pony | 4 + github_rest_api/_test.pony | 135 +-- github_rest_api/_test_json_converters.pony | 835 ++++++++++-------- github_rest_api/_test_mock_http_server.pony | 32 +- github_rest_api/_test_request_actors.pony | 657 +++++++++----- github_rest_api/_test_result_receivers.pony | 343 ++++--- .../_test_search_and_pagination.pony | 500 +++++++---- github_rest_api/asset.pony | 12 +- github_rest_api/commit.pony | 34 +- github_rest_api/commit_file.pony | 5 +- github_rest_api/gist.pony | 232 +++-- github_rest_api/gist_comment.pony | 93 +- github_rest_api/gist_commit.pony | 17 +- github_rest_api/gist_file.pony | 14 +- github_rest_api/git_commit.pony | 11 +- github_rest_api/git_person.pony | 2 +- github_rest_api/issue.pony | 195 ++-- github_rest_api/issue_comment.pony | 101 ++- github_rest_api/issue_pull_request.pony | 20 +- github_rest_api/label.pony | 84 +- github_rest_api/license.pony | 8 +- github_rest_api/linked_result_receiver.pony | 17 + github_rest_api/paginated_list.pony | 239 +++-- github_rest_api/pull_request.pony | 65 +- github_rest_api/pull_request_base.pony | 23 +- github_rest_api/pull_request_file.pony | 46 +- github_rest_api/release.pony | 96 +- github_rest_api/repository.pony | 412 ++++++--- github_rest_api/request/check_requester.pony | 8 +- github_rest_api/request/json_requester.pony | 10 +- .../request/no_content_requester.pony | 8 +- github_rest_api/search.pony | 128 ++- github_rest_api/user.pony | 11 +- 109 files changed, 4559 insertions(+), 2473 deletions(-) create mode 100644 .github/workflows/pony-lint.yml create mode 100644 examples/create-gist-oo/create_gist_oo.pony create mode 100644 examples/create-gist/create_gist.pony create mode 100644 examples/create-issue-comment-oo/create_issue_comment_oo.pony create mode 100644 examples/create-issue-comment/create_issue_comment.pony create mode 100644 examples/create-label-oo/create_label_oo.pony create mode 100644 examples/create-label/create_label.pony create mode 100644 examples/create-release-oo/create_release_oo.pony create mode 100644 examples/create-release/create_release.pony create mode 100644 examples/delete-label-oo/delete_label_oo.pony create mode 100644 examples/delete-label/delete_label.pony create mode 100644 examples/get-commit-oo/get_commit_oo.pony create mode 100644 examples/get-commit/get_commit.pony create mode 100644 examples/get-gist-oo/get_gist_oo.pony create mode 100644 examples/get-gist/get_gist.pony create mode 100644 examples/get-issue-comments-oo/get_issue_comments_oo.pony create mode 100644 examples/get-issue-comments/get_issue_comments.pony create mode 100644 examples/get-issue-oo/get_issue_oo.pony create mode 100644 examples/get-issue/get_issue.pony create mode 100644 examples/get-issues-oo/get_issues_oo.pony create mode 100644 examples/get-issues/get_issues.pony create mode 100644 examples/get-pull-request-files-oo/get_pull_request_files_oo.pony create mode 100644 examples/get-pull-request-files/get_pull_request_files.pony create mode 100644 examples/get-pull-request-oo/get_pull_request_oo.pony create mode 100644 examples/get-pull-request/get_pull_request.pony create mode 100644 examples/get-repository-labels/get_repository_labels.pony create mode 100644 examples/get-repository-oo/get_repository_oo.pony create mode 100644 examples/get-repository/get_repository.pony create mode 100644 examples/gist-comments-oo/gist_comments_oo.pony create mode 100644 examples/gist-comments/gist_comments.pony create mode 100644 examples/list-gists-oo/list_gists_oo.pony create mode 100644 examples/list-gists/list_gists.pony create mode 100644 examples/search-issues/search_issues.pony create mode 100644 examples/standard-pony-labels/standard_pony_labels.pony create mode 100644 examples/star-gist-oo/star_gist_oo.pony create mode 100644 examples/star-gist/star_gist.pony create mode 100644 github_rest_api/linked_result_receiver.pony diff --git a/.github/workflows/breakage-against-ponyc-latest.yml b/.github/workflows/breakage-against-ponyc-latest.yml index 258f092..695cdbb 100644 --- a/.github/workflows/breakage-against-ponyc-latest.yml +++ b/.github/workflows/breakage-against-ponyc-latest.yml @@ -1,4 +1,4 @@ -name: Test against ponyc nightly +name: ponyc update breakage test on: repository_dispatch: @@ -8,8 +8,29 @@ permissions: packages: read jobs: - vs-latest-ponyc: - name: Verify main against the latest ponyc + pony-lint: + name: Lint against ponyc main + runs-on: ubuntu-latest + container: + image: ghcr.io/ponylang/shared-docker-ci-standard-builder:nightly + steps: + - uses: actions/checkout@v6.0.2 + - name: Lint + run: make lint + - name: Send alert on failure + if: ${{ failure() }} + uses: zulip/github-actions-zulip/send-message@bd8ec52de371d139ae8313661b7d8318c19266aa + with: + api-key: ${{ secrets.ZULIP_SCHEDULED_JOB_FAILURE_API_KEY }} + email: ${{ secrets.ZULIP_SCHEDULED_JOB_FAILURE_EMAIL }} + organization-url: 'https://ponylang.zulipchat.com/' + to: notifications + type: stream + topic: ${{ github.repository }} scheduled job failure + content: ${{ github.server_url}}/${{ github.repository }}/actions/runs/${{ github.run_id }} failed. + + vs-ponyc-latest: + name: Test against ponyc main runs-on: ubuntu-latest container: image: ghcr.io/ponylang/shared-docker-ci-standard-builder-with-openssl-3.6.2:nightly diff --git a/.github/workflows/pony-lint.yml b/.github/workflows/pony-lint.yml new file mode 100644 index 0000000..5e4e20b --- /dev/null +++ b/.github/workflows/pony-lint.yml @@ -0,0 +1,24 @@ +name: pony-lint + +on: + pull_request: + paths: + - '**/*.pony' + +concurrency: + group: pony-lint-${{ github.ref }} + cancel-in-progress: true + +permissions: + packages: read + +jobs: + pony-lint: + name: Lint Pony source + runs-on: ubuntu-latest + container: + image: ghcr.io/ponylang/shared-docker-ci-standard-builder:release + steps: + - uses: actions/checkout@v6.0.2 + - name: Lint + run: make lint diff --git a/.release-notes/next-release.md b/.release-notes/next-release.md index 71eea60..131fb37 100644 --- a/.release-notes/next-release.md +++ b/.release-notes/next-release.md @@ -1,4 +1,48 @@ -## Update to work with Pony 0.69.1 +## Require Pony 0.69.1 -Pony 0.69.1 is the new minimum required version. +Pony 0.69.1 is the new minimum required version. The `json` standard library package renamed its types from `Json*` to `JSON*` in this release, and all public types in this library have been updated to match. + +## Rename Json to JSON in public type names + +All public types that had `Json` in their name now use `JSON` to follow Pony's acronym casing convention. This affects every converter primitive, the two paginated converter classes, and `LinkedJSONRequester`. + +Before: + +```pony +let converter = RepositoryJsonConverter +``` + +After: + +```pony +let converter = RepositoryJSONConverter +``` + +The full list of renamed types: + +- `AssetJsonConverter` → `AssetJSONConverter` +- `CommitJsonConverter` → `CommitJSONConverter` +- `CommitFileJsonConverter` → `CommitFileJSONConverter` +- `GistJsonConverter` → `GistJSONConverter` +- `GistChangeStatusJsonConverter` → `GistChangeStatusJSONConverter` +- `GistCommentJsonConverter` → `GistCommentJSONConverter` +- `GistCommitJsonConverter` → `GistCommitJSONConverter` +- `GistFileJsonConverter` → `GistFileJSONConverter` +- `GitCommitJsonConverter` → `GitCommitJSONConverter` +- `GitPersonJsonConverter` → `GitPersonJSONConverter` +- `IssueJsonConverter` → `IssueJSONConverter` +- `IssueCommentJsonConverter` → `IssueCommentJSONConverter` +- `IssueCommentsJsonConverter` → `IssueCommentsJSONConverter` +- `IssuePullRequestJsonConverter` → `IssuePullRequestJSONConverter` +- `LabelJsonConverter` → `LabelJSONConverter` +- `LicenseJsonConverter` → `LicenseJSONConverter` +- `PullRequestJsonConverter` → `PullRequestJSONConverter` +- `PullRequestBaseJsonConverter` → `PullRequestBaseJSONConverter` +- `PullRequestFilesJsonConverter` → `PullRequestFilesJSONConverter` +- `ReleaseJsonConverter` → `ReleaseJSONConverter` +- `RepositoryJsonConverter` → `RepositoryJSONConverter` +- `UserJsonConverter` → `UserJSONConverter` +- `PaginatedListJsonConverter` → `PaginatedListJSONConverter` +- `PaginatedSearchJsonConverter` → `PaginatedSearchJSONConverter` +- `LinkedJsonRequester` → `LinkedJSONRequester` diff --git a/AGENTS.md b/AGENTS.md index 2885bfd..e210b69 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -36,6 +36,7 @@ make unit-tests ssl=3.0.x # unit tests only make test-one t=TestName ssl=3.0.x # run a single test by name make examples ssl=3.0.x # build examples only make config=debug ssl=3.0.x # debug build +make lint # run pony-lint (no ssl= needed) make clean # clean build artifacts + corral deps ``` @@ -43,7 +44,7 @@ make clean # clean build artifacts + corral deps ## Architecture -Every API operation returns `Promise[(T | RequestError)]`. An operation primitive (for example `GetRepository`) builds the URL by RFC 6570 template expansion (`ponylang/uri`), then hands off to a short-lived request actor — `JsonRequester`, `NoContentRequester`, or `CheckRequester` in the `request/` subpackage — that owns a `courier` HTTP connection; the response is turned into a model by a `JsonConverter[T]`, and the promise is fulfilled with the model or a `RequestError`. Paginated results come back as `PaginatedList[A]`, whose `prev_page()`/`next_page()` fetch through `LinkedJsonRequester`, following the HTTP `Link` header (parsed by `ponylang/web_link`). +Every API operation returns `Promise[(T | RequestError)]`. An operation primitive (for example `GetRepository`) builds the URL by RFC 6570 template expansion (`ponylang/uri`), then hands off to a short-lived request actor — `JSONRequester`, `NoContentRequester`, or `CheckRequester` in the `request/` subpackage — that owns a `courier` HTTP connection; the response is turned into a model by a `JSONConverter[T]`, and the promise is fulfilled with the model or a `RequestError`. Paginated results come back as `PaginatedList[A]`, whose `prev_page()`/`next_page()` fetch through `LinkedJSONRequester`, following the HTTP `Link` header (parsed by `ponylang/web_link`). The `request/` subpackage is self-contained HTTP infrastructure — it imports nothing from the parent package. diff --git a/CHANGELOG.md b/CHANGELOG.md index c9a8fab..fe98064 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,8 @@ All notable changes to this project will be documented in this file. This projec ### Changed -- Update to work with Pony 0.69.1 ([PR #146](https://github.com/ponylang/github_rest_api/pull/146)) +- Require Pony 0.69.1 ([PR #146](https://github.com/ponylang/github_rest_api/pull/146)) +- Rename Json to JSON in public type names ([PR #147](https://github.com/ponylang/github_rest_api/pull/147)) ## [0.8.0] - 2026-08-07 diff --git a/Makefile b/Makefile index b7eb076..71833d3 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,7 @@ GET_DEPENDENCIES_WITH := corral fetch CLEAN_DEPENDENCIES_WITH := corral clean COMPILE_WITH := corral run -- ponyc BUILD_DOCS_WITH := corral run -- pony-doc +LINT_WITH := corral run -- pony-lint BUILD_DIR ?= build/$(config) SRC_DIR := $(PACKAGE) @@ -24,7 +25,7 @@ else PONYC = $(COMPILE_WITH) --debug endif -ifeq (,$(filter $(MAKECMDGOALS),clean docs realclean TAGS)) +ifeq (,$(filter $(MAKECMDGOALS),clean docs lint realclean TAGS)) ifeq ($(ssl), 3.0.x) SSL = -Dopenssl_3.0.x else ifeq ($(ssl), 1.1.x) @@ -66,6 +67,10 @@ _build_examples: $(EXAMPLES_BINARIES) $(EXAMPLES_BINARIES): $(BUILD_DIR)/%: $(SOURCE_FILES) $(EXAMPLES_SOURCE_FILES) | $(BUILD_DIR) BUILD_DIR=$(mkfile_path)$(BUILD_DIR) $(MAKE) -C $(EXAMPLES_DIR)/$* +lint: + $(GET_DEPENDENCIES_WITH) + $(LINT_WITH) . + clean: $(CLEAN_DEPENDENCIES_WITH) rm -rf $(BUILD_DIR) @@ -85,4 +90,4 @@ all: test $(BUILD_DIR): mkdir -p $(BUILD_DIR) -.PHONY: all examples _build_examples clean fetch TAGS test test-one +.PHONY: all examples _build_examples clean fetch lint TAGS test test-one diff --git a/README.md b/README.md index 6b7fafd..e8f71bc 100644 --- a/README.md +++ b/README.md @@ -23,11 +23,11 @@ Additional API surface and functionality will be added as needed. If you need fu ```pony use "github_rest_api" use "github_rest_api/request" -use "net" +use lori = "lori" actor Main new create(env: Env) => - let auth = TCPConnectAuth(env.root) + let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, "your-github-token") GitHub(creds).get_repo("ponylang", "ponyc") @@ -35,7 +35,7 @@ actor Main primitive PrintRepository fun apply(out: OutStream, result: RepositoryOrError) => - match result + match \exhaustive\ result | let repo: Repository => out.print(repo.full_name) | let err: RequestError => diff --git a/examples/create-gist-oo/create_gist_oo.pony b/examples/create-gist-oo/create_gist_oo.pony new file mode 100644 index 0000000..6aeeec5 --- /dev/null +++ b/examples/create-gist-oo/create_gist_oo.pony @@ -0,0 +1,4 @@ +""" +Demonstrates creating a GitHub gist using the GitHub object convenience +method. +""" diff --git a/examples/create-gist-oo/main.pony b/examples/create-gist-oo/main.pony index a149d37..19257cc 100644 --- a/examples/create-gist-oo/main.pony +++ b/examples/create-gist-oo/main.pony @@ -6,34 +6,44 @@ use lori = "lori" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("create-gist-oo", + CommandSpec.leaf( + "create-gist-oo", "Create a new gist with a single file", [ - OptionSpec.string("filename", "Name of the file to create") - OptionSpec.string("content", "Content of the file") - OptionSpec.string("description", + OptionSpec.string( + "filename", + "Name of the file to create") + OptionSpec.string( + "content", + "Content of the file") + OptionSpec.string( + "description", "Description of the gist" where default' = "") - OptionSpec.bool("public", + OptionSpec.bool( + "public", "Whether the gist should be public" where default' = false) - OptionSpec.string("token", "GitHub personal access token") + OptionSpec.string( + "token", + "GitHub personal access token") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let filename = cmd.option("filename").string() let content = cmd.option("content").string() @@ -41,18 +51,21 @@ actor Main let is_public = cmd.option("public").bool() let token = cmd.option("token").string() - // ----- Create gist let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) - let files = recover val - let f = Array[(String, String)] - f.push((filename, content)) - f - end + let files = + recover val + Array[(String, String)] + .> push((filename, content)) + end let desc: (String | None) = - if description.size() > 0 then description else None end + if description.size() > 0 then + description + else + None + end GitHub(creds).create_gist(files, desc, is_public) .next[None](PrintGist~apply(env.out)) @@ -61,6 +74,9 @@ actor Main end primitive PrintGist + """ + Prints gist details to the given output stream. + """ fun apply(out: OutStream, g: GistOrError) => match \exhaustive\ g | let gist: Gist => diff --git a/examples/create-gist/create_gist.pony b/examples/create-gist/create_gist.pony new file mode 100644 index 0000000..a7df059 --- /dev/null +++ b/examples/create-gist/create_gist.pony @@ -0,0 +1,3 @@ +""" +Demonstrates creating a GitHub gist using the CreateGist operation. +""" diff --git a/examples/create-gist/main.pony b/examples/create-gist/main.pony index 9c9743a..0946cfc 100644 --- a/examples/create-gist/main.pony +++ b/examples/create-gist/main.pony @@ -6,34 +6,44 @@ use lori = "lori" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("create-gist", + CommandSpec.leaf( + "create-gist", "Create a new gist with a single file", [ - OptionSpec.string("filename", "Name of the file to create") - OptionSpec.string("content", "Content of the file") - OptionSpec.string("description", + OptionSpec.string( + "filename", + "Name of the file to create") + OptionSpec.string( + "content", + "Content of the file") + OptionSpec.string( + "description", "Description of the gist" where default' = "") - OptionSpec.bool("public", + OptionSpec.bool( + "public", "Whether the gist should be public" where default' = false) - OptionSpec.string("token", "GitHub personal access token") + OptionSpec.string( + "token", + "GitHub personal access token") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let filename = cmd.option("filename").string() let content = cmd.option("content").string() @@ -41,18 +51,21 @@ actor Main let is_public = cmd.option("public").bool() let token = cmd.option("token").string() - // ----- Create gist let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) - let files = recover val - let f = Array[(String, String)] - f.push((filename, content)) - f - end + let files = + recover val + Array[(String, String)] + .> push((filename, content)) + end let desc: (String | None) = - if description.size() > 0 then description else None end + if description.size() > 0 then + description + else + None + end let p = CreateGist(files, creds, desc, is_public) p.next[None](PrintGist~apply(env.out)) @@ -61,6 +74,9 @@ actor Main end primitive PrintGist + """ + Prints gist details to the given output stream. + """ fun apply(out: OutStream, g: GistOrError) => match \exhaustive\ g | let gist: Gist => diff --git a/examples/create-issue-comment-oo/create_issue_comment_oo.pony b/examples/create-issue-comment-oo/create_issue_comment_oo.pony new file mode 100644 index 0000000..74960ca --- /dev/null +++ b/examples/create-issue-comment-oo/create_issue_comment_oo.pony @@ -0,0 +1,4 @@ +""" +Demonstrates creating a comment on a GitHub issue using the GitHub +object convenience method. +""" diff --git a/examples/create-issue-comment-oo/main.pony b/examples/create-issue-comment-oo/main.pony index e1d72f1..898fb1e 100644 --- a/examples/create-issue-comment-oo/main.pony +++ b/examples/create-issue-comment-oo/main.pony @@ -7,30 +7,40 @@ use "promises" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("create-issue-comment-oo", + CommandSpec.leaf( + "create-issue-comment-oo", "Create a comment on a GitHub issue", [ - OptionSpec.string("owner", "Owner of the repository the issue is in") - OptionSpec.string("repo", "Name of the repository the issue is in") + OptionSpec.string( + "owner", + "Owner of the repository") + OptionSpec.string( + "repo", + "Name of the repository") OptionSpec.i64("issue", "Issue number") - OptionSpec.string("comment", "Comment to add to the issue") - OptionSpec.string("token", "GitHub personal access token") + OptionSpec.string( + "comment", + "Comment to add to the issue") + OptionSpec.string( + "token", + "GitHub personal access token") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let owner = cmd.option("owner").string() let repo = cmd.option("repo").string() @@ -38,37 +48,55 @@ actor Main let comment = cmd.option("comment").string() let token = cmd.option("token").string() - // ----- Create issue comment let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) GitHub(creds).get_repo(owner, repo) - .flatten_next[IssueOrError](RetrieveIssue~apply(issue)) - .flatten_next[IssueCommentOrError](CreateComment~apply(comment)) - .next[None](PrintComment~apply(env.out)) + .flatten_next[IssueOrError]( + RetrieveIssue~apply(issue)) + .flatten_next[IssueCommentOrError]( + CreateComment~apply(comment)) + .next[None](PrintComment~apply(env.out)) else env.out.print("Something went wrong") end primitive RetrieveIssue - fun apply(number: I64, r: RepositoryOrError): Promise[IssueOrError] => + """ + Retrieves an issue from a repository result. + """ + fun apply( + number: I64, + r: RepositoryOrError) + : Promise[IssueOrError] + => match \exhaustive\ r | let repo: Repository => repo.get_issue(number) | let e: RequestError => - Promise[IssueOrError].>apply(e) + Promise[IssueOrError] .> apply(e) end primitive CreateComment - fun apply(body: String, i: IssueOrError): Promise[IssueCommentOrError] => + """ + Creates a comment on an issue result. + """ + fun apply( + body: String, + i: IssueOrError) + : Promise[IssueCommentOrError] + => match \exhaustive\ i | let issue: Issue => issue.create_comment(body) | let e: RequestError => - Promise[IssueCommentOrError].>apply(e) + Promise[IssueCommentOrError] .> apply(e) end primitive PrintComment + """ + Prints issue comment details to the given output stream. + """ fun apply(out: OutStream, c: IssueCommentOrError) => match \exhaustive\ c | let comment: IssueComment => diff --git a/examples/create-issue-comment/create_issue_comment.pony b/examples/create-issue-comment/create_issue_comment.pony new file mode 100644 index 0000000..eadf509 --- /dev/null +++ b/examples/create-issue-comment/create_issue_comment.pony @@ -0,0 +1,4 @@ +""" +Demonstrates creating a comment on a GitHub issue using the +CreateIssueComment operation. +""" diff --git a/examples/create-issue-comment/main.pony b/examples/create-issue-comment/main.pony index d1ea9b8..ac98e38 100644 --- a/examples/create-issue-comment/main.pony +++ b/examples/create-issue-comment/main.pony @@ -6,30 +6,40 @@ use lori = "lori" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("create-issue-comment", + CommandSpec.leaf( + "create-issue-comment", "Create a comment on a GitHub issue", [ - OptionSpec.string("owner", "Owner of the repository the issue is in") - OptionSpec.string("repo", "Name of the repository the issue is in") + OptionSpec.string( + "owner", + "Owner of the repository") + OptionSpec.string( + "repo", + "Name of the repository") OptionSpec.i64("issue", "Issue number") - OptionSpec.string("comment", "Comment to add to the issue") - OptionSpec.string("token", "GitHub personal access token") + OptionSpec.string( + "comment", + "Comment to add to the issue") + OptionSpec.string( + "token", + "GitHub personal access token") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let owner = cmd.option("owner").string() let repo = cmd.option("repo").string() @@ -37,17 +47,21 @@ actor Main let comment = cmd.option("comment").string() let token = cmd.option("token").string() - // ----- Create issue comment let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) - let p = CreateIssueComment(owner, repo, issue, comment, creds) + let p = + CreateIssueComment( + owner, repo, issue, comment, creds) p.next[None](PrintComment~apply(env.out)) else env.out.print("Something went wrong") end primitive PrintComment + """ + Prints issue comment details to the given output stream. + """ fun apply(out: OutStream, c: IssueCommentOrError) => match \exhaustive\ c | let comment: IssueComment => diff --git a/examples/create-label-oo/create_label_oo.pony b/examples/create-label-oo/create_label_oo.pony new file mode 100644 index 0000000..909b800 --- /dev/null +++ b/examples/create-label-oo/create_label_oo.pony @@ -0,0 +1,4 @@ +""" +Demonstrates creating a repository label using the GitHub object +convenience method. +""" diff --git a/examples/create-label-oo/main.pony b/examples/create-label-oo/main.pony index 36e0313..d35c646 100644 --- a/examples/create-label-oo/main.pony +++ b/examples/create-label-oo/main.pony @@ -2,38 +2,46 @@ use "../../github_rest_api" use "../../github_rest_api/request" use "cli" use lori = "lori" -use "promises" +use "promises" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("create-label-oo", + CommandSpec.leaf( + "create-label-oo", "Create a new label", [ OptionSpec.string( - "owner", "Owner of the repository to add the label to") + "owner", + "Owner of the repository") OptionSpec.string( - "repo", "Name of the repository to add the label to") + "repo", + "Name of the repository") OptionSpec.string("name", "Label name") OptionSpec.string("color", "Label color") - OptionSpec.string("description", "Label description") - OptionSpec.string("token", "GitHub personal access token") + OptionSpec.string( + "description", + "Label description") + OptionSpec.string( + "token", + "GitHub personal access token") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let owner = cmd.option("owner").string() let repo = cmd.option("repo").string() @@ -42,31 +50,39 @@ actor Main let description = cmd.option("description").string() let token = cmd.option("token").string() - // ----- Create issue comment let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) GitHub(creds).get_repo(owner, repo) - .flatten_next[LabelOrError](MakeLabel~apply(name, color, description)) + .flatten_next[LabelOrError]( + MakeLabel~apply(name, color, description)) .next[None](PrintLabel~apply(env.out)) else env.out.print("Something went wrong") end primitive MakeLabel - fun apply(name: String, + """ + Creates a label on a repository result. + """ + fun apply( + name: String, color: String, description: String, - r: RepositoryOrError): Promise[LabelOrError] + r: RepositoryOrError) + : Promise[LabelOrError] => match \exhaustive\ r | let repo: Repository => repo.create_label(name, color, description) | let e: RequestError => - Promise[LabelOrError].>apply(e) + Promise[LabelOrError] .> apply(e) end primitive PrintLabel + """ + Prints label details to the given output stream. + """ fun apply(out: OutStream, l: LabelOrError) => match \exhaustive\ l | let label: Label => diff --git a/examples/create-label/create_label.pony b/examples/create-label/create_label.pony new file mode 100644 index 0000000..b07dfc7 --- /dev/null +++ b/examples/create-label/create_label.pony @@ -0,0 +1,4 @@ +""" +Demonstrates creating a repository label using the CreateLabel +operation. +""" diff --git a/examples/create-label/main.pony b/examples/create-label/main.pony index e76ce8d..51d9fb8 100644 --- a/examples/create-label/main.pony +++ b/examples/create-label/main.pony @@ -6,33 +6,41 @@ use lori = "lori" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("create-label", + CommandSpec.leaf( + "create-label", "Create a new label", [ OptionSpec.string( - "owner", "Owner of the repository to add the label to") + "owner", + "Owner of the repository") OptionSpec.string( - "repo", "Name of the repository to add the label to") + "repo", + "Name of the repository") OptionSpec.string("name", "Label name") OptionSpec.string("color", "Label color") - OptionSpec.string("description", "Label description") - OptionSpec.string("token", "GitHub personal access token") + OptionSpec.string( + "description", + "Label description") + OptionSpec.string( + "token", + "GitHub personal access token") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let owner = cmd.option("owner").string() let repo = cmd.option("repo").string() @@ -41,17 +49,21 @@ actor Main let description = cmd.option("description").string() let token = cmd.option("token").string() - // ----- Create issue comment let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) - let p = CreateLabel(owner, repo, name, creds, color, description) + let p = + CreateLabel( + owner, repo, name, creds, color, description) p.next[None](PrintLabel~apply(env.out)) else env.out.print("Something went wrong") end primitive PrintLabel + """ + Prints label details to the given output stream. + """ fun apply(out: OutStream, l: LabelOrError) => match \exhaustive\ l | let label: Label => diff --git a/examples/create-release-oo/create_release_oo.pony b/examples/create-release-oo/create_release_oo.pony new file mode 100644 index 0000000..a6ab3c5 --- /dev/null +++ b/examples/create-release-oo/create_release_oo.pony @@ -0,0 +1,4 @@ +""" +Demonstrates creating a GitHub release using the GitHub object +convenience method. +""" diff --git a/examples/create-release-oo/main.pony b/examples/create-release-oo/main.pony index 6c3b84c..37d0fbf 100644 --- a/examples/create-release-oo/main.pony +++ b/examples/create-release-oo/main.pony @@ -7,31 +7,39 @@ use "promises" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("create-release-oo", + CommandSpec.leaf( + "create-release-oo", "Create a release", [ - OptionSpec.string("owner", "Owner of the repository the issue is in") - OptionSpec.string("repo", "Name of the repository the issue is in") + OptionSpec.string( + "owner", + "Owner of the repository") + OptionSpec.string( + "repo", + "Name of the repository") OptionSpec.string("tag", "Tag for release") OptionSpec.string("name", "Release name") OptionSpec.string("body", "Release notes") - OptionSpec.string("token", "GitHub personal access token") + OptionSpec.string( + "token", + "GitHub personal access token") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let owner = cmd.option("owner").string() let repo = cmd.option("repo").string() @@ -40,31 +48,39 @@ actor Main let body = cmd.option("body").string() let token = cmd.option("token").string() - // ----- Create release let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) GitHub(creds).get_repo(owner, repo) - .flatten_next[ReleaseOrError](MakeRelease~apply(tag_name, name, body)) + .flatten_next[ReleaseOrError]( + MakeRelease~apply(tag_name, name, body)) .next[None](PrintRelease~apply(env.out)) else env.out.print("Something went wrong") end primitive MakeRelease - fun apply(tag_name: String, + """ + Creates a release on a repository result. + """ + fun apply( + tag_name: String, name: String, body: String, - r: RepositoryOrError): Promise[ReleaseOrError] + r: RepositoryOrError) + : Promise[ReleaseOrError] => match \exhaustive\ r | let repo: Repository => repo.create_release(tag_name, name, body) | let e: RequestError => - Promise[ReleaseOrError].>apply(e) + Promise[ReleaseOrError] .> apply(e) end primitive PrintRelease + """ + Prints release details to the given output stream. + """ fun apply(out: OutStream, r: ReleaseOrError) => match \exhaustive\ r | let release: Release => diff --git a/examples/create-release/create_release.pony b/examples/create-release/create_release.pony new file mode 100644 index 0000000..3feeb2f --- /dev/null +++ b/examples/create-release/create_release.pony @@ -0,0 +1,4 @@ +""" +Demonstrates creating a GitHub release using the CreateRelease +operation. +""" diff --git a/examples/create-release/main.pony b/examples/create-release/main.pony index 1cba030..b84a864 100644 --- a/examples/create-release/main.pony +++ b/examples/create-release/main.pony @@ -6,31 +6,39 @@ use lori = "lori" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("create-release", + CommandSpec.leaf( + "create-release", "Create a release", [ - OptionSpec.string("owner", "Owner of the repository the issue is in") - OptionSpec.string("repo", "Name of the repository the issue is in") + OptionSpec.string( + "owner", + "Owner of the repository") + OptionSpec.string( + "repo", + "Name of the repository") OptionSpec.string("tag", "Tag for release") OptionSpec.string("name", "Release name") OptionSpec.string("body", "Release notes") - OptionSpec.string("token", "GitHub personal access token") + OptionSpec.string( + "token", + "GitHub personal access token") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let owner = cmd.option("owner").string() let repo = cmd.option("repo").string() @@ -39,17 +47,20 @@ actor Main let body = cmd.option("body").string() let token = cmd.option("token").string() - // ----- Create release let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) - CreateRelease(owner, repo, tag_name, name, body, creds) + CreateRelease( + owner, repo, tag_name, name, body, creds) .next[None](PrintRelease~apply(env.out)) else env.out.print("Something went wrong") end primitive PrintRelease + """ + Prints release details to the given output stream. + """ fun apply(out: OutStream, r: ReleaseOrError) => match \exhaustive\ r | let release: Release => diff --git a/examples/delete-label-oo/delete_label_oo.pony b/examples/delete-label-oo/delete_label_oo.pony new file mode 100644 index 0000000..912bc23 --- /dev/null +++ b/examples/delete-label-oo/delete_label_oo.pony @@ -0,0 +1,4 @@ +""" +Demonstrates deleting a repository label using the GitHub object +convenience method. +""" diff --git a/examples/delete-label-oo/main.pony b/examples/delete-label-oo/main.pony index 89938fc..4657565 100644 --- a/examples/delete-label-oo/main.pony +++ b/examples/delete-label-oo/main.pony @@ -7,62 +7,86 @@ use "promises" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("delete-label-oo", + CommandSpec.leaf( + "delete-label-oo", "Deletes an existing label", [ OptionSpec.string( - "owner", "Owner of the repository the label is part of") + "owner", + "Owner of the repository") OptionSpec.string( - "repo", "Name of the repository the label is part of") - OptionSpec.string("name", "Name of the label to delete") - OptionSpec.string("token", "GitHub personal access token") + "repo", + "Name of the repository") + OptionSpec.string( + "name", + "Name of the label to delete") + OptionSpec.string( + "token", + "GitHub personal access token") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let owner = cmd.option("owner").string() let repo = cmd.option("repo").string() let name = cmd.option("name").string() let token = cmd.option("token").string() - // ----- Create issue comment let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) GitHub(creds).get_repo(owner, repo) - .flatten_next[DeletedOrError](RemoveLabel~apply(name)) - .next[None](PrintResult~apply(env.out, name)) + .flatten_next[DeletedOrError]( + RemoveLabel~apply(name)) + .next[None]( + PrintResult~apply(env.out, name)) else env.out.print("Something went wrong") end primitive RemoveLabel - fun apply(label: String, r: RepositoryOrError): Promise[DeletedOrError] => + """ + Deletes a label from a repository result. + """ + fun apply( + label: String, + r: RepositoryOrError) + : Promise[DeletedOrError] + => match \exhaustive\ r | let repo: Repository => repo.delete_label(label) | let e: RequestError => - Promise[DeletedOrError].>apply(e) + Promise[DeletedOrError] .> apply(e) end primitive PrintResult - fun apply(out: OutStream, label: String, d: DeletedOrError) => + """ + Prints the result of a label deletion. + """ + fun apply( + out: OutStream, + label: String, + d: DeletedOrError) + => match \exhaustive\ d | Deleted => - out.print("Label " + label + " has been deleted") + out.print( + "Label " + label + " has been deleted") | let e: RequestError => out.print("Unable to delete label") out.print(e.status.string()) diff --git a/examples/delete-label/delete_label.pony b/examples/delete-label/delete_label.pony new file mode 100644 index 0000000..539342d --- /dev/null +++ b/examples/delete-label/delete_label.pony @@ -0,0 +1,4 @@ +""" +Demonstrates deleting a repository label using the DeleteLabel +operation. +""" diff --git a/examples/delete-label/main.pony b/examples/delete-label/main.pony index d5cefa7..818775a 100644 --- a/examples/delete-label/main.pony +++ b/examples/delete-label/main.pony @@ -6,52 +6,68 @@ use lori = "lori" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("delete-label", + CommandSpec.leaf( + "delete-label", "Deletes an existing label", [ OptionSpec.string( - "owner", "Owner of the repository the label is part of") + "owner", + "Owner of the repository") OptionSpec.string( - "repo", "Name of the repository the label is part of") - OptionSpec.string("name", "Name of the label to delete") - OptionSpec.string("token", "GitHub personal access token") + "repo", + "Name of the repository") + OptionSpec.string( + "name", + "Name of the label to delete") + OptionSpec.string( + "token", + "GitHub personal access token") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let owner = cmd.option("owner").string() let repo = cmd.option("repo").string() let name = cmd.option("name").string() let token = cmd.option("token").string() - // ----- Create issue comment let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) DeleteLabel(owner, repo, name, creds) - .next[None](PrintResult~apply(env.out, name)) + .next[None]( + PrintResult~apply(env.out, name)) else env.out.print("Something went wrong") end primitive PrintResult - fun apply(out: OutStream, label: String, d: DeletedOrError) => + """ + Prints the result of a label deletion. + """ + fun apply( + out: OutStream, + label: String, + d: DeletedOrError) + => match \exhaustive\ d | Deleted => - out.print("Label " + label + " has been deleted") + out.print( + "Label " + label + " has been deleted") | let e: RequestError => out.print("Unable to delete label") out.print(e.status.string()) diff --git a/examples/get-commit-oo/get_commit_oo.pony b/examples/get-commit-oo/get_commit_oo.pony new file mode 100644 index 0000000..8a56517 --- /dev/null +++ b/examples/get-commit-oo/get_commit_oo.pony @@ -0,0 +1,4 @@ +""" +Demonstrates retrieving a commit using the GitHub object convenience +method. +""" diff --git a/examples/get-commit-oo/main.pony b/examples/get-commit-oo/main.pony index 58a5348..a19e8c6 100644 --- a/examples/get-commit-oo/main.pony +++ b/examples/get-commit-oo/main.pony @@ -7,58 +7,77 @@ use "promises" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("get-commit-oo", + CommandSpec.leaf( + "get-commit-oo", "Get a commit", [ - OptionSpec.string("owner", "Owner of the repository the commit is in") - OptionSpec.string("repo", "Name of the repository the commit is in") - OptionSpec.string("sha", "Sha of the commit to retrieve") - OptionSpec.string("token", + OptionSpec.string( + "owner", + "Owner of the repository") + OptionSpec.string( + "repo", + "Name of the repository") + OptionSpec.string( + "sha", + "Sha of the commit to retrieve") + OptionSpec.string( + "token", "GitHub personal access token" where default' = "") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let owner = cmd.option("owner").string() let repo = cmd.option("repo").string() let sha = cmd.option("sha").string() let token = cmd.option("token").string() - // ----- Get commit let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) GitHub(creds).get_repo(owner, repo) - .flatten_next[CommitOrError](RetrieveCommit~apply(sha)) + .flatten_next[CommitOrError]( + RetrieveCommit~apply(sha)) .next[None](PrintCommit~apply(env.out)) else env.out.print("Something went wrong") end primitive RetrieveCommit - fun apply(sha: String, r: RepositoryOrError): Promise[CommitOrError] => + """ + Retrieves a commit from a repository result. + """ + fun apply( + sha: String, + r: RepositoryOrError) + : Promise[CommitOrError] + => match \exhaustive\ r | let repo: Repository => repo.get_commit(sha) | let e: RequestError => - Promise[CommitOrError].>apply(e) + Promise[CommitOrError] .> apply(e) end primitive PrintCommit + """ + Prints commit details to the given output stream. + """ fun apply(out: OutStream, c: CommitOrError) => match \exhaustive\ c | let commit: Commit => @@ -72,8 +91,10 @@ primitive PrintCommit end out.print("Git commit ==>") out.print(commit.git_commit.message) - out.print("author: " + commit.git_commit.author.name) - out.print("committer: " + commit.git_commit.committer.name) + out.print( + "author: " + commit.git_commit.author.name) + out.print("committer: " + + commit.git_commit.committer.name) | let e: RequestError => out.print("Unable to retrieve commit") out.print(e.status.string()) diff --git a/examples/get-commit/get_commit.pony b/examples/get-commit/get_commit.pony new file mode 100644 index 0000000..32cd998 --- /dev/null +++ b/examples/get-commit/get_commit.pony @@ -0,0 +1,3 @@ +""" +Demonstrates retrieving a commit using the GetCommit operation. +""" diff --git a/examples/get-commit/main.pony b/examples/get-commit/main.pony index 2d9f89f..769f9bb 100644 --- a/examples/get-commit/main.pony +++ b/examples/get-commit/main.pony @@ -6,38 +6,46 @@ use lori = "lori" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("get-commit", + CommandSpec.leaf( + "get-commit", "Get a commit", [ - OptionSpec.string("owner", "Owner of the repository the commit is in") - OptionSpec.string("repo", "Name of the repository the commit is in") - OptionSpec.string("sha", "Sha of the commit to retrieve") - OptionSpec.string("token", + OptionSpec.string( + "owner", + "Owner of the repository") + OptionSpec.string( + "repo", + "Name of the repository") + OptionSpec.string( + "sha", + "Sha of the commit to retrieve") + OptionSpec.string( + "token", "GitHub personal access token" where default' = "") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let owner = cmd.option("owner").string() let repo = cmd.option("repo").string() let sha = cmd.option("sha").string() let token = cmd.option("token").string() - // ----- Get commit let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) @@ -48,6 +56,9 @@ actor Main end primitive PrintCommit + """ + Prints commit details to the given output stream. + """ fun apply(out: OutStream, c: CommitOrError) => match \exhaustive\ c | let commit: Commit => @@ -61,8 +72,10 @@ primitive PrintCommit end out.print("Git commit ==>") out.print(commit.git_commit.message) - out.print("author: " + commit.git_commit.author.name) - out.print("committer: " + commit.git_commit.committer.name) + out.print( + "author: " + commit.git_commit.author.name) + out.print("committer: " + + commit.git_commit.committer.name) | let e: RequestError => out.print("Unable to retrieve commit") out.print(e.status.string()) diff --git a/examples/get-gist-oo/get_gist_oo.pony b/examples/get-gist-oo/get_gist_oo.pony new file mode 100644 index 0000000..1ad3f15 --- /dev/null +++ b/examples/get-gist-oo/get_gist_oo.pony @@ -0,0 +1,4 @@ +""" +Demonstrates fetching a GitHub gist by ID using the object +convenience method. +""" diff --git a/examples/get-gist-oo/main.pony b/examples/get-gist-oo/main.pony index c994e0d..f4b5b37 100644 --- a/examples/get-gist-oo/main.pony +++ b/examples/get-gist-oo/main.pony @@ -6,34 +6,39 @@ use lori = "lori" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("get-gist-oo", + CommandSpec.leaf( + "get-gist-oo", "Get information about a gist", [ - OptionSpec.string("gist-id", "ID of the gist to fetch") - OptionSpec.string("token", + OptionSpec.string( + "gist-id", + "ID of the gist to fetch") + OptionSpec.string( + "token", "GitHub personal access token" where default' = "") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, + env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let gist_id = cmd.option("gist-id").string() let token = cmd.option("token").string() - // ----- Get gist let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) @@ -44,6 +49,9 @@ actor Main end primitive PrintGist + """ + Prints details of a fetched gist to the given output stream. + """ fun apply(out: OutStream, g: GistOrError) => match \exhaustive\ g | let gist: Gist => @@ -54,7 +62,9 @@ primitive PrintGist out.print("Public: " + gist.public.string()) out.print("Files:") for (name, file) in gist.files.values() do - out.print(" " + name + " (" + file.size.string() + " bytes)") + out.print( + " " + name + " (" + + file.size.string() + " bytes)") end out.print(gist.html_url) | let e: RequestError => diff --git a/examples/get-gist/get_gist.pony b/examples/get-gist/get_gist.pony new file mode 100644 index 0000000..1163d6c --- /dev/null +++ b/examples/get-gist/get_gist.pony @@ -0,0 +1,4 @@ +""" +Demonstrates fetching a GitHub gist by ID using the GetGist +operation. +""" diff --git a/examples/get-gist/main.pony b/examples/get-gist/main.pony index 9c2951f..5153bd0 100644 --- a/examples/get-gist/main.pony +++ b/examples/get-gist/main.pony @@ -6,34 +6,39 @@ use lori = "lori" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("get-gist", + CommandSpec.leaf( + "get-gist", "Get information about a gist", [ - OptionSpec.string("gist-id", "ID of the gist to fetch") - OptionSpec.string("token", + OptionSpec.string( + "gist-id", + "ID of the gist to fetch") + OptionSpec.string( + "token", "GitHub personal access token" where default' = "") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, + env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let gist_id = cmd.option("gist-id").string() let token = cmd.option("token").string() - // ----- Get gist let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) @@ -44,6 +49,9 @@ actor Main end primitive PrintGist + """ + Prints details of a fetched gist to the given output stream. + """ fun apply(out: OutStream, g: GistOrError) => match \exhaustive\ g | let gist: Gist => @@ -54,7 +62,9 @@ primitive PrintGist out.print("Public: " + gist.public.string()) out.print("Files:") for (name, file) in gist.files.values() do - out.print(" " + name + " (" + file.size.string() + " bytes)") + out.print( + " " + name + " (" + + file.size.string() + " bytes)") end out.print(gist.html_url) | let e: RequestError => diff --git a/examples/get-issue-comments-oo/get_issue_comments_oo.pony b/examples/get-issue-comments-oo/get_issue_comments_oo.pony new file mode 100644 index 0000000..b255a2f --- /dev/null +++ b/examples/get-issue-comments-oo/get_issue_comments_oo.pony @@ -0,0 +1,4 @@ +""" +Demonstrates fetching comments on a GitHub issue using the object +convenience method. +""" diff --git a/examples/get-issue-comments-oo/main.pony b/examples/get-issue-comments-oo/main.pony index ac64680..e2117c7 100644 --- a/examples/get-issue-comments-oo/main.pony +++ b/examples/get-issue-comments-oo/main.pony @@ -7,69 +7,100 @@ use "promises" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("get-issue-comments-oo", + CommandSpec.leaf( + "get-issue-comments-oo", "Get all comments for an issue", [ - OptionSpec.string("owner", "Owner of the repository the issue is in") - OptionSpec.string("repo", "Name of the repository the issue is in") - OptionSpec.i64("issue", "Issue number to get comments for") - OptionSpec.string("token", + OptionSpec.string( + "owner", + "Owner of the repository the issue is in") + OptionSpec.string( + "repo", + "Name of the repository the issue is in") + OptionSpec.i64( + "issue", + "Issue number to get comments for") + OptionSpec.string( + "token", "GitHub personal access token" where default' = "") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, + env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let owner = cmd.option("owner").string() let repo = cmd.option("repo").string() let issue = cmd.option("issue").i64() let token = cmd.option("token").string() - // ----- Get issue comments let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) GitHub(creds).get_repo(owner, repo) - .flatten_next[IssueOrError](RetrieveIssue~apply(issue)) - .flatten_next[IssueCommentsOrError](RetrieveComments~apply()) - .next[None](PrintIssueComments~apply(env.out)) + .flatten_next[IssueOrError]( + RetrieveIssue~apply(issue)) + .flatten_next[IssueCommentsOrError]( + RetrieveComments~apply()) + .next[None]( + PrintIssueComments~apply(env.out)) else env.out.print("Something went wrong") end primitive RetrieveIssue - fun apply(number: I64, r: RepositoryOrError): Promise[IssueOrError] => + """ + Retrieves an issue from a repository result. + """ + fun apply( + number: I64, + r: RepositoryOrError) + : Promise[IssueOrError] + => match \exhaustive\ r | let repo: Repository => repo.get_issue(number) | let e: RequestError => - Promise[IssueOrError].>apply(e) + Promise[IssueOrError] .> apply(e) end primitive RetrieveComments - fun apply(i: IssueOrError): Promise[IssueCommentsOrError] => + """ + Retrieves comments from an issue result. + """ + fun apply( + i: IssueOrError) + : Promise[IssueCommentsOrError] + => match \exhaustive\ i | let issue: Issue => issue.get_comments() | let e: RequestError => - Promise[IssueCommentsOrError].>apply(e) + Promise[IssueCommentsOrError] .> apply(e) end primitive PrintIssueComments - fun apply(out: OutStream, r: IssueCommentsOrError) => + """ + Prints issue comments to the given output stream. + """ + fun apply( + out: OutStream, + r: IssueCommentsOrError) + => match \exhaustive\ r | let comments: Array[IssueComment] val => for c in comments.values() do diff --git a/examples/get-issue-comments/get_issue_comments.pony b/examples/get-issue-comments/get_issue_comments.pony new file mode 100644 index 0000000..376a2f1 --- /dev/null +++ b/examples/get-issue-comments/get_issue_comments.pony @@ -0,0 +1,4 @@ +""" +Demonstrates fetching comments on a GitHub issue using the +GetIssueComments operation. +""" diff --git a/examples/get-issue-comments/main.pony b/examples/get-issue-comments/main.pony index 47daad3..7ef6287 100644 --- a/examples/get-issue-comments/main.pony +++ b/examples/get-issue-comments/main.pony @@ -6,49 +6,66 @@ use lori = "lori" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("get-issue-comments", + CommandSpec.leaf( + "get-issue-comments", "Get all comments for an issue", [ - OptionSpec.string("owner", "Owner of the repository the issue is in") - OptionSpec.string("repo", "Name of the repository the issue is in") - OptionSpec.i64("issue", "Issue number to get comments for") - OptionSpec.string("token", + OptionSpec.string( + "owner", + "Owner of the repository the issue is in") + OptionSpec.string( + "repo", + "Name of the repository the issue is in") + OptionSpec.i64( + "issue", + "Issue number to get comments for") + OptionSpec.string( + "token", "GitHub personal access token" where default' = "") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, + env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let owner = cmd.option("owner").string() let repo = cmd.option("repo").string() let issue = cmd.option("issue").i64() let token = cmd.option("token").string() - // ----- Get issue comments let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) - let p = GetIssueComments(owner, repo, issue, creds) - p.next[None](PrintIssueComments~apply(env.out)) + let p = + GetIssueComments(owner, repo, issue, creds) + p.next[None]( + PrintIssueComments~apply(env.out)) else env.out.print("Something went wrong") end primitive PrintIssueComments - fun apply(out: OutStream, r: IssueCommentsOrError) => + """ + Prints issue comments to the given output stream. + """ + fun apply( + out: OutStream, + r: IssueCommentsOrError) + => match \exhaustive\ r | let comments: Array[IssueComment] val => for c in comments.values() do diff --git a/examples/get-issue-oo/get_issue_oo.pony b/examples/get-issue-oo/get_issue_oo.pony new file mode 100644 index 0000000..7cb29fe --- /dev/null +++ b/examples/get-issue-oo/get_issue_oo.pony @@ -0,0 +1,4 @@ +""" +Demonstrates fetching a GitHub issue by number using the object +convenience method. +""" diff --git a/examples/get-issue-oo/main.pony b/examples/get-issue-oo/main.pony index 5c73d0a..d0b8ef4 100644 --- a/examples/get-issue-oo/main.pony +++ b/examples/get-issue-oo/main.pony @@ -7,58 +7,78 @@ use "promises" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("get-issue-oo", + CommandSpec.leaf( + "get-issue-oo", "Get an issue", [ - OptionSpec.string("owner", "Owner of the repository the issue is in") - OptionSpec.string("repo", "Name of the repository the issue is in") - OptionSpec.i64("issue", "Issue number to retrieve") - OptionSpec.string("token", + OptionSpec.string( + "owner", + "Owner of the repository the issue is in") + OptionSpec.string( + "repo", + "Name of the repository the issue is in") + OptionSpec.i64( + "issue", + "Issue number to retrieve") + OptionSpec.string( + "token", "GitHub personal access token" where default' = "") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, + env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let owner = cmd.option("owner").string() let repo = cmd.option("repo").string() let issue = cmd.option("issue").i64() let token = cmd.option("token").string() - // ----- Get issue let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) GitHub(creds).get_repo(owner, repo) - .flatten_next[IssueOrError](RetrieveIssue~apply(issue)) - .next[None](PrintIssue~apply(env.out)) + .flatten_next[IssueOrError]( + RetrieveIssue~apply(issue)) + .next[None](PrintIssue~apply(env.out)) else env.out.print("Something went wrong") end primitive RetrieveIssue - fun apply(number: I64, r: RepositoryOrError): Promise[IssueOrError] => + """ + Retrieves an issue from a repository result. + """ + fun apply( + number: I64, + r: RepositoryOrError) + : Promise[IssueOrError] + => match \exhaustive\ r | let repo: Repository => repo.get_issue(number) | let e: RequestError => - Promise[IssueOrError].>apply(e) + Promise[IssueOrError] .> apply(e) end primitive PrintIssue + """ + Prints details of a fetched issue to the given output stream. + """ fun apply(out: OutStream, i: IssueOrError) => match \exhaustive\ i | let issue: Issue => diff --git a/examples/get-issue/get_issue.pony b/examples/get-issue/get_issue.pony new file mode 100644 index 0000000..745252f --- /dev/null +++ b/examples/get-issue/get_issue.pony @@ -0,0 +1,4 @@ +""" +Demonstrates fetching a GitHub issue by number using the GetIssue +operation. +""" diff --git a/examples/get-issue/main.pony b/examples/get-issue/main.pony index 5267db1..df371bd 100644 --- a/examples/get-issue/main.pony +++ b/examples/get-issue/main.pony @@ -6,38 +6,47 @@ use lori = "lori" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("get-issue", + CommandSpec.leaf( + "get-issue", "Get an issue", [ - OptionSpec.string("owner", "Owner of the repository the issue is in") - OptionSpec.string("repo", "Name of the repository the issue is in") - OptionSpec.i64("issue", "Issue number to retrieve") - OptionSpec.string("token", + OptionSpec.string( + "owner", + "Owner of the repository the issue is in") + OptionSpec.string( + "repo", + "Name of the repository the issue is in") + OptionSpec.i64( + "issue", + "Issue number to retrieve") + OptionSpec.string( + "token", "GitHub personal access token" where default' = "") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, + env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let owner = cmd.option("owner").string() let repo = cmd.option("repo").string() let issue = cmd.option("issue").i64() let token = cmd.option("token").string() - // ----- Get issue let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) @@ -48,6 +57,9 @@ actor Main end primitive PrintIssue + """ + Prints details of a fetched issue to the given output stream. + """ fun apply(out: OutStream, i: IssueOrError) => match \exhaustive\ i | let issue: Issue => diff --git a/examples/get-issues-oo/get_issues_oo.pony b/examples/get-issues-oo/get_issues_oo.pony new file mode 100644 index 0000000..bb0867c --- /dev/null +++ b/examples/get-issues-oo/get_issues_oo.pony @@ -0,0 +1,4 @@ +""" +Demonstrates listing issues in a repository using the object +convenience method. +""" diff --git a/examples/get-issues-oo/main.pony b/examples/get-issues-oo/main.pony index f47d632..85f3600 100644 --- a/examples/get-issues-oo/main.pony +++ b/examples/get-issues-oo/main.pony @@ -7,48 +7,63 @@ use "promises" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("get-issues-oo", + CommandSpec.leaf( + "get-issues-oo", "List issues in a repository", [ - OptionSpec.string("owner", "Owner of the repository") - OptionSpec.string("repo", "Name of the repository") - OptionSpec.string("token", + OptionSpec.string( + "owner", + "Owner of the repository") + OptionSpec.string( + "repo", + "Name of the repository") + OptionSpec.string( + "token", "GitHub personal access token" where default' = "") - OptionSpec.string("labels", + OptionSpec.string( + "labels", "Comma-separated label names to filter by" where default' = "") - OptionSpec.string("state", + OptionSpec.string( + "state", "Issue state: open, closed, or all" where default' = "open") - OptionSpec.string("sort", + OptionSpec.string( + "sort", "Sort field: created, updated, or comments" where default' = "created") - OptionSpec.string("direction", + OptionSpec.string( + "direction", "Sort direction: asc or desc" where default' = "desc") - OptionSpec.string("since", - "Only issues updated at or after this ISO 8601 timestamp" + OptionSpec.string( + "since", + "Only issues updated at or after " + + "this ISO 8601 timestamp" where default' = "") - OptionSpec.i64("per-page", + OptionSpec.i64( + "per-page", "Results per page (1-100, default 30)" where default' = 0) ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, + env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let owner = cmd.option("owner").string() let repo = cmd.option("repo").string() @@ -56,34 +71,43 @@ actor Main let labels = cmd.option("labels").string() let state = cmd.option("state").string() let sort_str = cmd.option("sort").string() - let direction_str = cmd.option("direction").string() + let direction_str = + cmd.option("direction").string() let since = cmd.option("since").string() let per_page_i = cmd.option("per-page").i64() - let sort: IssueSort = match sort_str - | "updated" => SortByUpdated - | "comments" => SortByComments - else SortByCreated - end + let sort: IssueSort = + match sort_str + | "updated" => SortByUpdated + | "comments" => SortByComments + else SortByCreated + end - let direction: SortDirection = match direction_str - | "asc" => SortAscending - else SortDescending - end + let direction: SortDirection = + match direction_str + | "asc" => SortAscending + else SortDescending + end - let per_page: (I64 | None) = if per_page_i > 0 then - per_page_i - else - None - end + let per_page: (I64 | None) = + if per_page_i > 0 then + per_page_i + else + None + end - // ----- Get issues let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) GitHub(creds).get_repo(owner, repo) - .flatten_next[(PaginatedList[Issue] | RequestError)]( - RetrieveIssues~apply(labels, state, sort, direction, since, + .flatten_next[ + (PaginatedList[Issue] | RequestError)]( + RetrieveIssues~apply( + labels, + state, + sort, + direction, + since, per_page)) .next[None](PrintIssues~apply(env.out)) else @@ -91,7 +115,11 @@ actor Main end primitive RetrieveIssues - fun apply(labels: String, + """ + Retrieves issues from a repository result. + """ + fun apply( + labels: String, state: String, sort: IssueSort, direction: SortDirection, @@ -102,38 +130,57 @@ primitive RetrieveIssues => match \exhaustive\ r | let repo: Repository => - repo.get_issues(labels, state, sort, direction, since, per_page) + repo.get_issues( + labels, + state, + sort, + direction, + since, + per_page) | let e: RequestError => - Promise[(PaginatedList[Issue] | RequestError)].>apply(e) + Promise[ + (PaginatedList[Issue] | RequestError)] + .> apply(e) end primitive PrintIssues - fun apply(out: OutStream, + """ + Prints a paginated list of issues to the given output stream. + """ + fun apply( + out: OutStream, r: (PaginatedList[Issue] | RequestError)) => match \exhaustive\ r | let list: PaginatedList[Issue] => for issue in list.results.values() do - let state = match issue.state - | let s: String => s - else "unknown" - end + let state = + match issue.state + | let s: String => s + else "unknown" + end out.print( - "#" + issue.number.string() - + " [" + state + "] " - + issue.title) + "#" + issue.number.string() + + " [" + state + "] " + + issue.title) if issue.labels.size() > 0 then let label_names = recover trn String end for (i, label) in issue.labels.pairs() do - if i > 0 then label_names.append(", ") end + if i > 0 then + label_names.append(", ") + end label_names.append(label.name) end - out.print(" Labels: " + consume label_names) + out.print( + " Labels: " + consume label_names) end end match list.next_page() - | let promise: Promise[(PaginatedList[Issue] | RequestError)] => - promise.next[None](PrintIssues~apply(out)) + | let promise: Promise[ + (PaginatedList[Issue] | RequestError)] + => + promise.next[None]( + PrintIssues~apply(out)) else out.print("------- No more issues") end diff --git a/examples/get-issues/get_issues.pony b/examples/get-issues/get_issues.pony new file mode 100644 index 0000000..961aef9 --- /dev/null +++ b/examples/get-issues/get_issues.pony @@ -0,0 +1,4 @@ +""" +Demonstrates listing issues in a repository using the +GetRepositoryIssues operation. +""" diff --git a/examples/get-issues/main.pony b/examples/get-issues/main.pony index 5f2d003..72bff0b 100644 --- a/examples/get-issues/main.pony +++ b/examples/get-issues/main.pony @@ -7,48 +7,63 @@ use "promises" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("get-issues", + CommandSpec.leaf( + "get-issues", "List issues in a repository", [ - OptionSpec.string("owner", "Owner of the repository") - OptionSpec.string("repo", "Name of the repository") - OptionSpec.string("token", + OptionSpec.string( + "owner", + "Owner of the repository") + OptionSpec.string( + "repo", + "Name of the repository") + OptionSpec.string( + "token", "GitHub personal access token" where default' = "") - OptionSpec.string("labels", + OptionSpec.string( + "labels", "Comma-separated label names to filter by" where default' = "") - OptionSpec.string("state", + OptionSpec.string( + "state", "Issue state: open, closed, or all" where default' = "open") - OptionSpec.string("sort", + OptionSpec.string( + "sort", "Sort field: created, updated, or comments" where default' = "created") - OptionSpec.string("direction", + OptionSpec.string( + "direction", "Sort direction: asc or desc" where default' = "desc") - OptionSpec.string("since", - "Only issues updated at or after this ISO 8601 timestamp" + OptionSpec.string( + "since", + "Only issues updated at or after " + + "this ISO 8601 timestamp" where default' = "") - OptionSpec.i64("per-page", + OptionSpec.i64( + "per-page", "Results per page (1-100, default 30)" where default' = 0) ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, + env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let owner = cmd.option("owner").string() let repo = cmd.option("repo").string() @@ -56,70 +71,88 @@ actor Main let labels = cmd.option("labels").string() let state = cmd.option("state").string() let sort_str = cmd.option("sort").string() - let direction_str = cmd.option("direction").string() + let direction_str = + cmd.option("direction").string() let since = cmd.option("since").string() let per_page_i = cmd.option("per-page").i64() - let sort: IssueSort = match sort_str - | "updated" => SortByUpdated - | "comments" => SortByComments - else SortByCreated - end + let sort: IssueSort = + match sort_str + | "updated" => SortByUpdated + | "comments" => SortByComments + else SortByCreated + end - let direction: SortDirection = match direction_str - | "asc" => SortAscending - else SortDescending - end + let direction: SortDirection = + match direction_str + | "asc" => SortAscending + else SortDescending + end - let per_page: (I64 | None) = if per_page_i > 0 then - per_page_i - else - None - end + let per_page: (I64 | None) = + if per_page_i > 0 then + per_page_i + else + None + end - // ----- Get issues let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) - let p = GetRepositoryIssues(owner, repo, creds - where labels = labels, - state = state, - sort = sort, - direction = direction, - since = since, - per_page = per_page) + let p = + GetRepositoryIssues( + owner, + repo, + creds + where labels = labels, + state = state, + sort = sort, + direction = direction, + since = since, + per_page = per_page) p.next[None](PrintIssues~apply(env.out)) else env.out.print("Something went wrong") end primitive PrintIssues - fun apply(out: OutStream, + """ + Prints a paginated list of issues to the given output stream. + """ + fun apply( + out: OutStream, r: (PaginatedList[Issue] | RequestError)) => match \exhaustive\ r | let list: PaginatedList[Issue] => for issue in list.results.values() do - let state = match issue.state - | let s: String => s - else "unknown" - end + let state = + match issue.state + | let s: String => s + else "unknown" + end out.print( - "#" + issue.number.string() - + " [" + state + "] " - + issue.title) + "#" + issue.number.string() + + " [" + state + "] " + + issue.title) if issue.labels.size() > 0 then let label_names = recover trn String end for (i, label) in issue.labels.pairs() do - if i > 0 then label_names.append(", ") end + if i > 0 then + label_names.append(", ") + end label_names.append(label.name) end - out.print(" Labels: " + consume label_names) + out.print( + " Labels: " + consume label_names) end end match list.next_page() - | let promise: Promise[(PaginatedList[Issue] | RequestError)] => - promise.next[None](PrintIssues~apply(out)) + | let promise: Promise[ + (PaginatedList[Issue] | RequestError)] + => + promise.next[None]( + PrintIssues~apply(out)) else out.print("------- No more issues") end diff --git a/examples/get-pull-request-files-oo/get_pull_request_files_oo.pony b/examples/get-pull-request-files-oo/get_pull_request_files_oo.pony new file mode 100644 index 0000000..f049cc9 --- /dev/null +++ b/examples/get-pull-request-files-oo/get_pull_request_files_oo.pony @@ -0,0 +1,4 @@ +""" +Demonstrates fetching files changed in a pull request using the +object convenience method. +""" diff --git a/examples/get-pull-request-files-oo/main.pony b/examples/get-pull-request-files-oo/main.pony index d102d29..5d18eab 100644 --- a/examples/get-pull-request-files-oo/main.pony +++ b/examples/get-pull-request-files-oo/main.pony @@ -7,76 +7,108 @@ use "promises" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("get-pull-request-files-oo", + CommandSpec.leaf( + "get-pull-request-files-oo", "Get all files for a pull request", [ - OptionSpec.string("owner", "Owner of the repository the issue is in") - OptionSpec.string("repo", "Name of the repository the issue is in") - OptionSpec.i64("pr", "Pullrequest number to get files for") - OptionSpec.string("token", + OptionSpec.string( + "owner", + "Owner of the repository") + OptionSpec.string( + "repo", + "Name of the repository") + OptionSpec.i64( + "pr", + "Pull request number to get files for") + OptionSpec.string( + "token", "GitHub personal access token" where default' = "") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, + env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let owner = cmd.option("owner").string() let repo = cmd.option("repo").string() let pr = cmd.option("pr").i64() let token = cmd.option("token").string() - // ----- Get pull request files let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) GitHub(creds).get_repo(owner, repo) - .flatten_next[PullRequestOrError](RetrievePullRequest~apply(pr)) - .flatten_next[PullRequestFilesOrError](RetrievePullReqestFiles~apply()) - .next[None](PrintPullRequestFiles~apply(env.out)) + .flatten_next[PullRequestOrError]( + RetrievePullRequest~apply(pr)) + .flatten_next[PullRequestFilesOrError]( + RetrievePullRequestFiles~apply()) + .next[None]( + PrintPullRequestFiles~apply(env.out)) else env.out.print("Something went wrong") end primitive RetrievePullRequest - fun apply(number: I64, r: RepositoryOrError): Promise[PullRequestOrError] => + """ + Retrieves a pull request from a repository result. + """ + fun apply( + number: I64, + r: RepositoryOrError) + : Promise[PullRequestOrError] + => match \exhaustive\ r | let repo: Repository => repo.get_pull_request(number) | let e: RequestError => - Promise[PullRequestOrError].>apply(e) + Promise[PullRequestOrError] .> apply(e) end -primitive RetrievePullReqestFiles - fun apply(p: PullRequestOrError): Promise[PullRequestFilesOrError] => +primitive RetrievePullRequestFiles + """ + Retrieves files from a pull request result. + """ + fun apply( + p: PullRequestOrError) + : Promise[PullRequestFilesOrError] + => match \exhaustive\ p | let pr: PullRequest => pr.get_files() | let e: RequestError => - Promise[PullRequestFilesOrError].>apply(e) + Promise[PullRequestFilesOrError] .> apply(e) end primitive PrintPullRequestFiles - fun apply(out: OutStream, r: PullRequestFilesOrError) => + """ + Prints pull request file names to the given output stream. + """ + fun apply( + out: OutStream, + r: PullRequestFilesOrError) + => match \exhaustive\ r | let files: Array[PullRequestFile] val => for f in files.values() do out.print(f.filename) end | let e: RequestError => - out.print("Unable to retrieve pull request files") + out.print( + "Unable to retrieve pull request files") out.print(e.status.string()) out.print(e.response_body) out.print(e.message) diff --git a/examples/get-pull-request-files/get_pull_request_files.pony b/examples/get-pull-request-files/get_pull_request_files.pony new file mode 100644 index 0000000..e2a4040 --- /dev/null +++ b/examples/get-pull-request-files/get_pull_request_files.pony @@ -0,0 +1,4 @@ +""" +Demonstrates fetching files changed in a pull request using the +GetPullRequestFiles operation. +""" diff --git a/examples/get-pull-request-files/main.pony b/examples/get-pull-request-files/main.pony index 86abf35..16f53e7 100644 --- a/examples/get-pull-request-files/main.pony +++ b/examples/get-pull-request-files/main.pony @@ -6,56 +6,74 @@ use lori = "lori" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("get-pull-request-files", + CommandSpec.leaf( + "get-pull-request-files", "Get all files for a pull request", [ - OptionSpec.string("owner", "Owner of the repository the issue is in") - OptionSpec.string("repo", "Name of the repository the issue is in") - OptionSpec.i64("pr", "Pullrequest number to get files for") - OptionSpec.string("token", + OptionSpec.string( + "owner", + "Owner of the repository") + OptionSpec.string( + "repo", + "Name of the repository") + OptionSpec.i64( + "pr", + "Pull request number to get files for") + OptionSpec.string( + "token", "GitHub personal access token" where default' = "") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, + env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let owner = cmd.option("owner").string() let repo = cmd.option("repo").string() let pr = cmd.option("pr").i64() let token = cmd.option("token").string() - // ----- Get pull request files let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) - let p = GetPullRequestFiles(owner, repo, pr, creds) - p.next[None](PrintPullRequestFiles~apply(env.out)) + let p = + GetPullRequestFiles(owner, repo, pr, creds) + p.next[None]( + PrintPullRequestFiles~apply(env.out)) else env.out.print("Something went wrong") end primitive PrintPullRequestFiles - fun apply(out: OutStream, r: PullRequestFilesOrError) => + """ + Prints pull request file names to the given output stream. + """ + fun apply( + out: OutStream, + r: PullRequestFilesOrError) + => match \exhaustive\ r | let files: Array[PullRequestFile] val => for f in files.values() do out.print(f.filename) end | let e: RequestError => - out.print("Unable to retrieve pull request files") + out.print( + "Unable to retrieve pull request files") out.print(e.status.string()) out.print(e.response_body) out.print(e.message) diff --git a/examples/get-pull-request-oo/get_pull_request_oo.pony b/examples/get-pull-request-oo/get_pull_request_oo.pony new file mode 100644 index 0000000..44bcb92 --- /dev/null +++ b/examples/get-pull-request-oo/get_pull_request_oo.pony @@ -0,0 +1,4 @@ +""" +Demonstrates fetching a GitHub pull request using the object +convenience method. +""" diff --git a/examples/get-pull-request-oo/main.pony b/examples/get-pull-request-oo/main.pony index 1f618af..7cb0cf3 100644 --- a/examples/get-pull-request-oo/main.pony +++ b/examples/get-pull-request-oo/main.pony @@ -7,61 +7,83 @@ use "promises" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("get-pull-request-oo", + CommandSpec.leaf( + "get-pull-request-oo", "Get pull request", [ - OptionSpec.string("owner", "Owner of the repository the issue is in") - OptionSpec.string("repo", "Name of the repository the issue is in") - OptionSpec.i64("pr", "Pull request number to retrieve") - OptionSpec.string("token", + OptionSpec.string( + "owner", + "Owner of the repository") + OptionSpec.string( + "repo", + "Name of the repository") + OptionSpec.i64( + "pr", + "Pull request number to retrieve") + OptionSpec.string( + "token", "GitHub personal access token" where default' = "") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, + env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let owner = cmd.option("owner").string() let repo = cmd.option("repo").string() let pr = cmd.option("pr").i64() let token = cmd.option("token").string() - // ----- Get pull request let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) GitHub(creds).get_repo(owner, repo) - .flatten_next[PullRequestOrError](RetrievePullRequest~apply(pr)) - .next[None](PrintPullRequest~apply(env.out)) + .flatten_next[PullRequestOrError]( + RetrievePullRequest~apply(pr)) + .next[None]( + PrintPullRequest~apply(env.out)) let p = GetPullRequest(owner, repo, pr, creds) - p.next[None](PrintPullRequest~apply(env.out)) + p.next[None]( + PrintPullRequest~apply(env.out)) else env.out.print("Something went wrong") end primitive RetrievePullRequest - fun apply(number: I64, r: RepositoryOrError): Promise[PullRequestOrError] => + """ + Retrieves a pull request from a repository result. + """ + fun apply( + number: I64, + r: RepositoryOrError) + : Promise[PullRequestOrError] + => match \exhaustive\ r | let repo: Repository => repo.get_pull_request(number) | let e: RequestError => - Promise[PullRequestOrError].>apply(e) + Promise[PullRequestOrError] .> apply(e) end primitive PrintPullRequest + """ + Prints details of a pull request to the given output stream. + """ fun apply(out: OutStream, p: PullRequestOrError) => match \exhaustive\ p | let pr: PullRequest => diff --git a/examples/get-pull-request/get_pull_request.pony b/examples/get-pull-request/get_pull_request.pony new file mode 100644 index 0000000..f981df3 --- /dev/null +++ b/examples/get-pull-request/get_pull_request.pony @@ -0,0 +1,4 @@ +""" +Demonstrates fetching a GitHub pull request using the GetPullRequest +operation. +""" diff --git a/examples/get-pull-request/main.pony b/examples/get-pull-request/main.pony index 8e31597..ae0751c 100644 --- a/examples/get-pull-request/main.pony +++ b/examples/get-pull-request/main.pony @@ -6,48 +6,61 @@ use lori = "lori" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("get-pull-request", + CommandSpec.leaf( + "get-pull-request", "Get pull request", [ - OptionSpec.string("owner", "Owner of the repository the issue is in") - OptionSpec.string("repo", "Name of the repository the issue is in") - OptionSpec.i64("pr", "Pull request number to retrieve") - OptionSpec.string("token", + OptionSpec.string( + "owner", + "Owner of the repository") + OptionSpec.string( + "repo", + "Name of the repository") + OptionSpec.i64( + "pr", + "Pull request number to retrieve") + OptionSpec.string( + "token", "GitHub personal access token" where default' = "") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, + env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let owner = cmd.option("owner").string() let repo = cmd.option("repo").string() let pr = cmd.option("pr").i64() let token = cmd.option("token").string() - // ----- Get pull request let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) let p = GetPullRequest(owner, repo, pr, creds) - p.next[None](PrintPullRequest~apply(env.out)) + p.next[None]( + PrintPullRequest~apply(env.out)) else env.out.print("Something went wrong") end primitive PrintPullRequest + """ + Prints details of a pull request to the given output stream. + """ fun apply(out: OutStream, p: PullRequestOrError) => match \exhaustive\ p | let pr: PullRequest => diff --git a/examples/get-repository-labels/get_repository_labels.pony b/examples/get-repository-labels/get_repository_labels.pony new file mode 100644 index 0000000..30c7a0d --- /dev/null +++ b/examples/get-repository-labels/get_repository_labels.pony @@ -0,0 +1,3 @@ +""" +Demonstrates fetching all labels for a GitHub repository. +""" diff --git a/examples/get-repository-labels/main.pony b/examples/get-repository-labels/main.pony index 16300f9..817841c 100644 --- a/examples/get-repository-labels/main.pony +++ b/examples/get-repository-labels/main.pony @@ -7,47 +7,60 @@ use "promises" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("get-repository-labels", + CommandSpec.leaf( + "get-repository-labels", "Get all labels for a repository", [ - OptionSpec.string("owner", "Owner of the repository the issue is in") - OptionSpec.string("repo", "Name of the repository the issue is in") - OptionSpec.string("token", + OptionSpec.string( + "owner", + "Owner of the repository") + OptionSpec.string( + "repo", + "Name of the repository") + OptionSpec.string( + "token", "GitHub personal access token" where default' = "") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let owner = cmd.option("owner").string() let repo = cmd.option("repo").string() let token = cmd.option("token").string() - // ----- Get repository let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) let p = GetRepositoryLabels(owner, repo, creds) - p.next[None](PrintRepositoryLabels~apply(env.out)) + p.next[None]( + PrintRepositoryLabels~apply(env.out)) else env.out.print("Something went wrong") end primitive PrintRepositoryLabels - fun apply(out: OutStream, l: (PaginatedList[Label] | RequestError)) => + """ + Prints repository labels to the given output stream. + """ + fun apply( + out: OutStream, + l: (PaginatedList[Label] | RequestError)) + => match \exhaustive\ l | let pl: PaginatedList[Label] => for label in pl.results.values() do @@ -65,8 +78,11 @@ primitive PrintRepositoryLabels out.print("") end match pl.next_page() - | let promise: Promise[(PaginatedList[Label] | RequestError)] => - promise.next[None](PrintRepositoryLabels~apply(out)) + | let promise: Promise[ + (PaginatedList[Label] | RequestError)] + => + promise.next[None]( + PrintRepositoryLabels~apply(out)) else out.print("------- No more labels") end diff --git a/examples/get-repository-oo/get_repository_oo.pony b/examples/get-repository-oo/get_repository_oo.pony new file mode 100644 index 0000000..9a74980 --- /dev/null +++ b/examples/get-repository-oo/get_repository_oo.pony @@ -0,0 +1,4 @@ +""" +Demonstrates fetching repository information using the object +convenience method. +""" diff --git a/examples/get-repository-oo/main.pony b/examples/get-repository-oo/main.pony index 0a82411..32f57c0 100644 --- a/examples/get-repository-oo/main.pony +++ b/examples/get-repository-oo/main.pony @@ -6,36 +6,42 @@ use lori = "lori" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("get-repository-oo", + CommandSpec.leaf( + "get-repository-oo", "Get information about a repository", [ - OptionSpec.string("owner", "Owner of the repository the issue is in") - OptionSpec.string("repo", "Name of the repository the issue is in") - OptionSpec.string("token", + OptionSpec.string( + "owner", + "Owner of the repository") + OptionSpec.string( + "repo", + "Name of the repository") + OptionSpec.string( + "token", "GitHub personal access token" where default' = "") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let owner = cmd.option("owner").string() let repo = cmd.option("repo").string() let token = cmd.option("token").string() - // ----- Get repository let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) @@ -46,6 +52,9 @@ actor Main end primitive PrintRepository + """ + Prints repository details to the given output stream. + """ fun apply(out: OutStream, c: RepositoryOrError) => match \exhaustive\ c | let repo: Repository => diff --git a/examples/get-repository/get_repository.pony b/examples/get-repository/get_repository.pony new file mode 100644 index 0000000..934e9eb --- /dev/null +++ b/examples/get-repository/get_repository.pony @@ -0,0 +1,3 @@ +""" +Demonstrates fetching information about a GitHub repository. +""" diff --git a/examples/get-repository/main.pony b/examples/get-repository/main.pony index a260f40..45f7b8e 100644 --- a/examples/get-repository/main.pony +++ b/examples/get-repository/main.pony @@ -6,36 +6,42 @@ use lori = "lori" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("get-repository", + CommandSpec.leaf( + "get-repository", "Get information about a repository", [ - OptionSpec.string("owner", "Owner of the repository the issue is in") - OptionSpec.string("repo", "Name of the repository the issue is in") - OptionSpec.string("token", + OptionSpec.string( + "owner", + "Owner of the repository") + OptionSpec.string( + "repo", + "Name of the repository") + OptionSpec.string( + "token", "GitHub personal access token" where default' = "") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let owner = cmd.option("owner").string() let repo = cmd.option("repo").string() let token = cmd.option("token").string() - // ----- Get repository let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) @@ -46,6 +52,9 @@ actor Main end primitive PrintRepository + """ + Prints repository details to the given output stream. + """ fun apply(out: OutStream, c: RepositoryOrError) => match \exhaustive\ c | let repo: Repository => diff --git a/examples/gist-comments-oo/gist_comments_oo.pony b/examples/gist-comments-oo/gist_comments_oo.pony new file mode 100644 index 0000000..b446289 --- /dev/null +++ b/examples/gist-comments-oo/gist_comments_oo.pony @@ -0,0 +1,4 @@ +""" +Demonstrates listing comments on a GitHub gist using the object +convenience method. +""" diff --git a/examples/gist-comments-oo/main.pony b/examples/gist-comments-oo/main.pony index dfd1276..73f90e4 100644 --- a/examples/gist-comments-oo/main.pony +++ b/examples/gist-comments-oo/main.pony @@ -7,39 +7,44 @@ use "promises" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("gist-comments-oo", + CommandSpec.leaf( + "gist-comments-oo", "List comments on a gist", [ - OptionSpec.string("gist-id", "ID of the gist") - OptionSpec.string("token", + OptionSpec.string( + "gist-id", + "ID of the gist") + OptionSpec.string( + "token", "GitHub personal access token" where default' = "") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let gist_id = cmd.option("gist-id").string() let token = cmd.option("token").string() - // ----- Get gist comments via OO API let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) GitHub(creds).get_gist(gist_id) - .flatten_next[(PaginatedList[GistComment] | RequestError)]( + .flatten_next[ + (PaginatedList[GistComment] | RequestError)]( RetrieveComments~apply()) .next[None](PrintComments~apply(env.out)) else @@ -47,30 +52,45 @@ actor Main end primitive RetrieveComments - fun apply(g: GistOrError) - : Promise[(PaginatedList[GistComment] | RequestError)] + """ + Retrieves comments for a gist from the API result. + """ + fun apply( + g: GistOrError) + : Promise[ + (PaginatedList[GistComment] | RequestError)] => match \exhaustive\ g | let gist: Gist => gist.get_comments() | let e: RequestError => - Promise[(PaginatedList[GistComment] | RequestError)].>apply(e) + Promise[ + (PaginatedList[GistComment] | RequestError)] + .> apply(e) end primitive PrintComments - fun apply(out: OutStream, + """ + Prints gist comments to the given output stream. + """ + fun apply( + out: OutStream, r: (PaginatedList[GistComment] | RequestError)) => match \exhaustive\ r | let list: PaginatedList[GistComment] => for c in list.results.values() do - out.print("Comment #" + c.id.string() + " ==>") + out.print( + "Comment #" + c.id.string() + " ==>") out.print(c.body) out.print("") end match list.next_page() - | let promise: Promise[(PaginatedList[GistComment] | RequestError)] => - promise.next[None](PrintComments~apply(out)) + | let promise: Promise[ + (PaginatedList[GistComment] | RequestError)] + => + promise.next[None]( + PrintComments~apply(out)) else out.print("------- No more comments") end diff --git a/examples/gist-comments/gist_comments.pony b/examples/gist-comments/gist_comments.pony new file mode 100644 index 0000000..ea4e49f --- /dev/null +++ b/examples/gist-comments/gist_comments.pony @@ -0,0 +1,3 @@ +""" +Demonstrates listing comments on a GitHub gist. +""" diff --git a/examples/gist-comments/main.pony b/examples/gist-comments/main.pony index 237e218..6d83d08 100644 --- a/examples/gist-comments/main.pony +++ b/examples/gist-comments/main.pony @@ -7,34 +7,38 @@ use "promises" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("gist-comments", + CommandSpec.leaf( + "gist-comments", "List comments on a gist", [ - OptionSpec.string("gist-id", "ID of the gist") - OptionSpec.string("token", + OptionSpec.string( + "gist-id", + "ID of the gist") + OptionSpec.string( + "token", "GitHub personal access token" where default' = "") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let gist_id = cmd.option("gist-id").string() let token = cmd.option("token").string() - // ----- Get gist comments let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) @@ -45,19 +49,27 @@ actor Main end primitive PrintComments - fun apply(out: OutStream, + """ + Prints gist comments to the given output stream. + """ + fun apply( + out: OutStream, r: (PaginatedList[GistComment] | RequestError)) => match \exhaustive\ r | let list: PaginatedList[GistComment] => for c in list.results.values() do - out.print("Comment #" + c.id.string() + " ==>") + out.print( + "Comment #" + c.id.string() + " ==>") out.print(c.body) out.print("") end match list.next_page() - | let promise: Promise[(PaginatedList[GistComment] | RequestError)] => - promise.next[None](PrintComments~apply(out)) + | let promise: Promise[ + (PaginatedList[GistComment] | RequestError)] + => + promise.next[None]( + PrintComments~apply(out)) else out.print("------- No more comments") end diff --git a/examples/list-gists-oo/list_gists_oo.pony b/examples/list-gists-oo/list_gists_oo.pony new file mode 100644 index 0000000..c03ff2a --- /dev/null +++ b/examples/list-gists-oo/list_gists_oo.pony @@ -0,0 +1,4 @@ +""" +Demonstrates listing the authenticated user's gists using the object +convenience method. +""" diff --git a/examples/list-gists-oo/main.pony b/examples/list-gists-oo/main.pony index d41d247..76802d2 100644 --- a/examples/list-gists-oo/main.pony +++ b/examples/list-gists-oo/main.pony @@ -7,30 +7,33 @@ use "promises" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("list-gists-oo", + CommandSpec.leaf( + "list-gists-oo", "List the authenticated user's gists", [ - OptionSpec.string("token", "GitHub personal access token") + OptionSpec.string( + "token", + "GitHub personal access token") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let token = cmd.option("token").string() - // ----- List gists let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) @@ -41,21 +44,29 @@ actor Main end primitive PrintGists - fun apply(out: OutStream, + """ + Prints gist summaries to the given output stream. + """ + fun apply( + out: OutStream, r: (PaginatedList[Gist] | RequestError)) => match \exhaustive\ r | let list: PaginatedList[Gist] => for gist in list.results.values() do - let desc = match gist.description - | let d: String => d - else "(no description)" - end + let desc = + match gist.description + | let d: String => d + else "(no description)" + end out.print(gist.id + " - " + desc) end match list.next_page() - | let promise: Promise[(PaginatedList[Gist] | RequestError)] => - promise.next[None](PrintGists~apply(out)) + | let promise: Promise[ + (PaginatedList[Gist] | RequestError)] + => + promise.next[None]( + PrintGists~apply(out)) else out.print("------- No more gists") end diff --git a/examples/list-gists/list_gists.pony b/examples/list-gists/list_gists.pony new file mode 100644 index 0000000..d939973 --- /dev/null +++ b/examples/list-gists/list_gists.pony @@ -0,0 +1,3 @@ +""" +Demonstrates listing the authenticated user's gists. +""" diff --git a/examples/list-gists/main.pony b/examples/list-gists/main.pony index c4ad197..b4f1d95 100644 --- a/examples/list-gists/main.pony +++ b/examples/list-gists/main.pony @@ -7,30 +7,33 @@ use "promises" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("list-gists", + CommandSpec.leaf( + "list-gists", "List the authenticated user's gists", [ - OptionSpec.string("token", "GitHub personal access token") + OptionSpec.string( + "token", + "GitHub personal access token") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let token = cmd.option("token").string() - // ----- List gists let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) @@ -41,21 +44,29 @@ actor Main end primitive PrintGists - fun apply(out: OutStream, + """ + Prints gist summaries to the given output stream. + """ + fun apply( + out: OutStream, r: (PaginatedList[Gist] | RequestError)) => match \exhaustive\ r | let list: PaginatedList[Gist] => for gist in list.results.values() do - let desc = match gist.description - | let d: String => d - else "(no description)" - end + let desc = + match gist.description + | let d: String => d + else "(no description)" + end out.print(gist.id + " - " + desc) end match list.next_page() - | let promise: Promise[(PaginatedList[Gist] | RequestError)] => - promise.next[None](PrintGists~apply(out)) + | let promise: Promise[ + (PaginatedList[Gist] | RequestError)] + => + promise.next[None]( + PrintGists~apply(out)) else out.print("------- No more gists") end diff --git a/examples/search-issues/main.pony b/examples/search-issues/main.pony index 05515cf..4da15a0 100644 --- a/examples/search-issues/main.pony +++ b/examples/search-issues/main.pony @@ -7,34 +7,38 @@ use "promises" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("search-issues", + CommandSpec.leaf( + "search-issues", "Search issues", [ - OptionSpec.string("query", "Query string") - OptionSpec.string("token", + OptionSpec.string( + "query", + "Query string") + OptionSpec.string( + "token", "GitHub personal access token" where default' = "") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let query = cmd.option("query").string() let token = cmd.option("token").string() - // ----- Search issues let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) @@ -45,16 +49,30 @@ actor Main end primitive PrintResults - fun apply(out: OutStream, r: IssueSearchResultsOrError) => + """ + Prints issue search results to the given output stream. + """ + fun apply( + out: OutStream, + r: IssueSearchResultsOrError) + => match \exhaustive\ r | let results: SearchResults[Issue] => - out.print("Total results: " + results.total_count.string()) + out.print( + "Total results: " + + results.total_count.string()) for i in results.items.values() do - out.print(i.title + " #" + i.number.string() + " " + i.html_url) + out.print( + i.title + " #" + + i.number.string() + " " + + i.html_url) end match results.next_page() - | let promise: Promise[IssueSearchResultsOrError] => - promise.next[None](PrintResults~apply(out)) + | let promise: Promise[ + IssueSearchResultsOrError] + => + promise.next[None]( + PrintResults~apply(out)) else out.print("------- No more results") end diff --git a/examples/search-issues/search_issues.pony b/examples/search-issues/search_issues.pony new file mode 100644 index 0000000..11e2585 --- /dev/null +++ b/examples/search-issues/search_issues.pony @@ -0,0 +1,4 @@ +""" +Demonstrates searching GitHub issues by query string with paginated +results. +""" diff --git a/examples/standard-pony-labels/main.pony b/examples/standard-pony-labels/main.pony index c5eca48..a6823a3 100644 --- a/examples/standard-pony-labels/main.pony +++ b/examples/standard-pony-labels/main.pony @@ -7,47 +7,59 @@ use "promises" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("standard-pony-labels", - "Deletes all labels in a repo and creates the standard ponylang ones", + CommandSpec.leaf( + "standard-pony-labels", + "Deletes all labels and creates standard ones", [ OptionSpec.string( - "owner", "Owner of the repository the label is part of") + "owner", + "Owner of the repository") OptionSpec.string( - "repo", "Name of the repository the label is part of") - OptionSpec.string("token", "GitHub personal access token") + "repo", + "Name of the repository") + OptionSpec.string( + "token", + "GitHub personal access token") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let owner = cmd.option("owner").string() let repo = cmd.option("repo").string() let token = cmd.option("token").string() - // ----- Create issue comment let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) let p = GetRepositoryLabels(owner, repo, creds) - .next[None](RemoveLabels~apply(env.out, owner, repo, creds)) + .next[None]( + RemoveLabels~apply( + env.out, owner, repo, creds)) else env.out.print("Something went wrong") end primitive RemoveLabels - fun apply(out: OutStream, + """ + Deletes all labels in a repository, then creates + the standard ponylang labels. + """ + fun apply( + out: OutStream, owner: String, repo: String, creds: Credentials, @@ -60,33 +72,47 @@ primitive RemoveLabels while index < pl.results.size() do let label = pl.results(index)? - let start_next = (pl.next_page() is None) - and (index == (pl.results.size() - 1)) + let start_next = + (pl.next_page() is None) and + (index == (pl.results.size() - 1)) - out.print("Deleting " + label.name + " label") - DeleteLabel(owner, repo, label.name, creds) - .next[None](NotifyLabelDeleted~apply(out, - owner, - repo, - creds, - label.name, - start_next)) + out.print( + "Deleting " + label.name + " label") + DeleteLabel( + owner, repo, label.name, creds) + .next[None]( + NotifyLabelDeleted~apply( + out, + owner, + repo, + creds, + label.name, + start_next)) index = index + 1 end end match pl.next_page() - | let promise: Promise[(PaginatedList[Label] | RequestError)] => - promise.next[None](RemoveLabels~apply(out, owner, repo, creds)) + | let promise: Promise[ + (PaginatedList[Label] | RequestError)] + => + promise.next[None]( + RemoveLabels~apply( + out, owner, repo, creds)) end | let e: RequestError => - out.print("Unable to retrieve repository labels") + out.print( + "Unable to retrieve repository labels") out.print(e.status.string()) out.print(e.response_body) out.print(e.message) end primitive NotifyLabelDeleted - fun apply(out: OutStream, + """ + Handles the result of deleting a label. + """ + fun apply( + out: OutStream, owner: String, repo: String, creds: Credentials, @@ -96,53 +122,91 @@ primitive NotifyLabelDeleted => match \exhaustive\ d | Deleted => - out.print("Label " + label + " has been deleted") + out.print( + "Label " + label + " has been deleted") if cont then CreatePonyLabels(out, owner, repo, creds) end | let e: RequestError => - out.print("Unable to delete " + label + " label") + out.print( + "Unable to delete " + label + " label") out.print(e.status.string()) out.print(e.response_body) out.print(e.message) end primitive CreatePonyLabels - fun apply(out: OutStream, + """ + Creates the standard ponylang labels in a + repository. + """ + fun apply( + out: OutStream, owner: String, repo: String, creds: Credentials) => - let standard_pony_labels: Array[(String, String, String)] val = [ - ("bug", "f7c6c7", "Something isn't working") - ("changelog - added", "ffaa55", "Automatically add \"Added\" CHANGELOG entry on merge") - ("changelog - changed", "ff7755", "Automatically add \"Changed\" CHANGELOG entry on merge") - ("changelog - fixed", "77aa55", "Automatically add \"Fixed\" CHANGELOG entry on merge") - ("do not merge", "d93f0b", "This PR should not be merged at this time") - ("documentation", "0075ca", "Improvements or additions to documentation") - ("enhancement", "a2eeef", "New feature or request") - ("good first issue", "7057ff", "Good for newcomers") - ("help wanted", "008672", "Extra attention is needed") - ("needs discussion", "ffffdd", "Needs to be discussed further") - ("needs investigation", "D3D3D3", "This needs to be looked into before it's \"ready for work\"") - ("triggers release", "006b75", "Major issue that when fixed, results in an \"emergency\" release") - ("discuss during sync", "CC1F71", "Should be discussed during an upcoming sync") - ] + let standard_pony_labels: + Array[(String, String, String)] val = + [ + ("bug", "f7c6c7", + "Something isn't working") + ("changelog - added", "ffaa55", + "Automatically add \"Added\" entry") + ("changelog - changed", "ff7755", + "Automatically add \"Changed\" entry") + ("changelog - fixed", "77aa55", + "Automatically add \"Fixed\" entry") + ("do not merge", "d93f0b", + "This PR should not be merged") + ("documentation", "0075ca", + "Improvements or additions to docs") + ("enhancement", "a2eeef", + "New feature or request") + ("good first issue", "7057ff", + "Good for newcomers") + ("help wanted", "008672", + "Extra attention is needed") + ("needs discussion", "ffffdd", + "Needs to be discussed further") + ("needs investigation", "D3D3D3", + "Needs investigation before work") + ("triggers release", "006b75", + "Results in an emergency release") + ("discuss during sync", "CC1F71", + "Discuss during an upcoming sync") + ] for label in standard_pony_labels.values() do - CreateLabel(owner, repo, label._1, creds, label._2, label._3) - .next[None](NotifyLabelCreated~apply(out, label._1)) + CreateLabel( + owner, + repo, + label._1, + creds, + label._2, + label._3) + .next[None]( + NotifyLabelCreated~apply( + out, label._1)) end primitive NotifyLabelCreated - fun apply(out: OutStream, label: String, l: LabelOrError) => + """ + Handles the result of creating a label. + """ + fun apply( + out: OutStream, + label: String, + l: LabelOrError) + => match \exhaustive\ l | let l': Label => - out.print("Label " + label + " created") + out.print( + "Label " + label + " created") | let e: RequestError => - out.print("Unable to create " + label + " label") + out.print( + "Unable to create " + label + " label") out.print(e.status.string()) out.print(e.response_body) out.print(e.message) end - diff --git a/examples/standard-pony-labels/standard_pony_labels.pony b/examples/standard-pony-labels/standard_pony_labels.pony new file mode 100644 index 0000000..0061c9c --- /dev/null +++ b/examples/standard-pony-labels/standard_pony_labels.pony @@ -0,0 +1,4 @@ +""" +Demonstrates replacing all labels in a repository with the standard +ponylang label set. +""" diff --git a/examples/star-gist-oo/main.pony b/examples/star-gist-oo/main.pony index 0b1dee3..d1dacee 100644 --- a/examples/star-gist-oo/main.pony +++ b/examples/star-gist-oo/main.pony @@ -7,69 +7,85 @@ use "promises" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("star-gist-oo", - "Star a gist and then check if it is starred", + CommandSpec.leaf( + "star-gist-oo", + "Star a gist then check if it is starred", [ - OptionSpec.string("gist-id", "ID of the gist to star") - OptionSpec.string("token", "GitHub personal access token") + OptionSpec.string( + "gist-id", + "ID of the gist to star") + OptionSpec.string( + "token", + "GitHub personal access token") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let gist_id = cmd.option("gist-id").string() let token = cmd.option("token").string() - // ----- Star gist then check via OO API let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) GitHub(creds).get_gist(gist_id) - .flatten_next[DeletedOrError](StarIt~apply()) - .flatten_next[BoolOrError](CheckIt~apply()) + .flatten_next[DeletedOrError]( + StarIt~apply()) + .flatten_next[BoolOrError]( + CheckIt~apply()) .next[None](PrintResult~apply(env.out)) else env.out.print("Something went wrong") end primitive StarIt + """ + Stars a gist from the API result. + """ fun apply(g: GistOrError): Promise[DeletedOrError] => match \exhaustive\ g | let gist: Gist => gist.star() | let e: RequestError => - Promise[DeletedOrError].>apply(e) + Promise[DeletedOrError] .> apply(e) end primitive CheckIt - fun apply(d: DeletedOrError): Promise[BoolOrError] => + """ + Checks star status after starring. + """ + fun apply( + d: DeletedOrError): Promise[BoolOrError] + => match \exhaustive\ d | Deleted => - // Star succeeded. We can't call is_starred() here because we don't - // have the Gist reference in this chain step. In real code, keep the - // Gist accessible or use the functional API (see star-gist example). - Promise[BoolOrError].>apply(true) + Promise[BoolOrError] .> apply(true) | let e: RequestError => - Promise[BoolOrError].>apply(e) + Promise[BoolOrError] .> apply(e) end primitive PrintResult + """ + Prints whether a gist is starred. + """ fun apply(out: OutStream, r: BoolOrError) => match \exhaustive\ r | let starred: Bool => - out.print("Is starred: " + starred.string()) + out.print( + "Is starred: " + starred.string()) | let e: RequestError => out.print("Error") out.print(e.status.string()) diff --git a/examples/star-gist-oo/star_gist_oo.pony b/examples/star-gist-oo/star_gist_oo.pony new file mode 100644 index 0000000..5e936a7 --- /dev/null +++ b/examples/star-gist-oo/star_gist_oo.pony @@ -0,0 +1,4 @@ +""" +Demonstrates starring a GitHub gist and checking whether it is starred +using the object convenience method. +""" diff --git a/examples/star-gist/main.pony b/examples/star-gist/main.pony index 79e77ce..480a2ba 100644 --- a/examples/star-gist/main.pony +++ b/examples/star-gist/main.pony @@ -7,32 +7,37 @@ use "promises" actor Main new create(env: Env) => try - // ----- CLI setup let cs = - CommandSpec.leaf("star-gist", - "Star a gist and then check if it is starred", + CommandSpec.leaf( + "star-gist", + "Star a gist then check if it is starred", [ - OptionSpec.string("gist-id", "ID of the gist to star") - OptionSpec.string("token", "GitHub personal access token") + OptionSpec.string( + "gist-id", + "ID of the gist to star") + OptionSpec.string( + "token", + "GitHub personal access token") ] )? .> add_help()? - let cmd = match \exhaustive\ CommandParser(cs).parse(env.args, env.vars) - | let c: Command => - c - | let ch: CommandHelp => - ch.print_help(env.out) - return - | let se: SyntaxError => - env.err.print(se.string()) - env.exitcode(1) - return - end + let cmd = + match \exhaustive\ CommandParser(cs).parse( + env.args, env.vars) + | let c: Command => + c + | let ch: CommandHelp => + ch.print_help(env.out) + return + | let se: SyntaxError => + env.err.print(se.string()) + env.exitcode(1) + return + end let gist_id = cmd.option("gist-id").string() let token = cmd.option("token").string() - // ----- Star gist then check let auth = lori.TCPConnectAuth(env.root) let creds = Credentials(auth, token) @@ -45,7 +50,11 @@ actor Main end primitive CheckStar - fun apply(gist_id: String, + """ + Checks whether a gist is starred after starring it. + """ + fun apply( + gist_id: String, creds: Credentials, d: DeletedOrError): Promise[BoolOrError] => @@ -53,14 +62,18 @@ primitive CheckStar | Deleted => CheckGistStar(gist_id, creds) | let e: RequestError => - Promise[BoolOrError].>apply(e) + Promise[BoolOrError] .> apply(e) end primitive PrintResult + """ + Prints whether a gist is starred. + """ fun apply(out: OutStream, r: BoolOrError) => match \exhaustive\ r | let starred: Bool => - out.print("Is starred: " + starred.string()) + out.print( + "Is starred: " + starred.string()) | let e: RequestError => out.print("Error") out.print(e.status.string()) diff --git a/examples/star-gist/star_gist.pony b/examples/star-gist/star_gist.pony new file mode 100644 index 0000000..04ff9c7 --- /dev/null +++ b/examples/star-gist/star_gist.pony @@ -0,0 +1,4 @@ +""" +Demonstrates starring a GitHub gist and checking whether it is +starred. +""" diff --git a/github_rest_api/_test.pony b/github_rest_api/_test.pony index 8411d9f..c6f005e 100644 --- a/github_rest_api/_test.pony +++ b/github_rest_api/_test.pony @@ -15,41 +15,41 @@ actor \nodoc\ Main is TestList test(_TestExtractPaginationLinksFirstPage) test(_TestExtractPaginationLinksLastPage) test(_TestExtractPaginationLinksBetweenPages) - test(_TestGitPersonJsonConverterPreservesValues) - test(_TestGitPersonJsonConverterMissingField) - test(_TestLicenseJsonConverterPreservesValues) - test(_TestLicenseJsonConverterMissingField) - test(_TestCommitFileJsonConverterPreservesValues) - test(_TestCommitFileJsonConverterMissingField) - test(_TestGistChangeStatusJsonConverterPreservesValues) - test(_TestGistChangeStatusJsonConverterMissingField) - test(_TestLabelJsonConverterPreservesValues) - test(_TestLabelJsonConverterMissingField) - test(_TestIssuePRJsonConverterPreservesValues) - test(_TestIssuePRJsonConverterMissingField) - test(_TestAssetJsonConverterPreservesValues) - test(_TestAssetJsonConverterMissingField) - test(_TestGistFileJsonConverterPreservesValues) - test(_TestGistFileJsonConverterMissingField) - test(_TestGistFileJsonConverterAbsentOptionalFields) - test(_TestGitCommitJsonConverterPreservesValues) - test(_TestGitCommitJsonConverterMissingField) - test(_TestCommitJsonConverterPreservesValues) - test(_TestCommitJsonConverterMissingField) - test(_TestIssueJsonConverterPreservesValues) - test(_TestIssueJsonConverterMissingField) - test(_TestIssueJsonConverterAbsentPullRequest) - test(_TestRepoJsonConverterPreservesValues) - test(_TestRepoJsonConverterMissingField) - test(_TestRepoJsonConverterAbsentOptionalFields) - test(_TestGistJsonConverterPreservesValues) - test(_TestGistJsonConverterMissingField) - test(_TestGistJsonConverterAbsentOptionalFields) + test(_TestGitPersonJSONConverterPreservesValues) + test(_TestGitPersonJSONConverterMissingField) + test(_TestLicenseJSONConverterPreservesValues) + test(_TestLicenseJSONConverterMissingField) + test(_TestCommitFileJSONConverterPreservesValues) + test(_TestCommitFileJSONConverterMissingField) + test(_TestGistChangeStatusJSONConverterPreservesValues) + test(_TestGistChangeStatusJSONConverterMissingField) + test(_TestLabelJSONConverterPreservesValues) + test(_TestLabelJSONConverterMissingField) + test(_TestIssuePRJSONConverterPreservesValues) + test(_TestIssuePRJSONConverterMissingField) + test(_TestAssetJSONConverterPreservesValues) + test(_TestAssetJSONConverterMissingField) + test(_TestGistFileJSONConverterPreservesValues) + test(_TestGistFileJSONConverterMissingField) + test(_TestGistFileJSONConverterAbsentOptionalFields) + test(_TestGitCommitJSONConverterPreservesValues) + test(_TestGitCommitJSONConverterMissingField) + test(_TestCommitJSONConverterPreservesValues) + test(_TestCommitJSONConverterMissingField) + test(_TestIssueJSONConverterPreservesValues) + test(_TestIssueJSONConverterMissingField) + test(_TestIssueJSONConverterAbsentPullRequest) + test(_TestRepoJSONConverterPreservesValues) + test(_TestRepoJSONConverterMissingField) + test(_TestRepoJSONConverterAbsentOptionalFields) + test(_TestGistJSONConverterPreservesValues) + test(_TestGistJSONConverterMissingField) + test(_TestGistJSONConverterAbsentOptionalFields) test(_TestStringOrNoneReturnsString) test(_TestStringOrNoneReturnsNone) test(_TestStringOrNoneRaisesOnInvalid) - test(_TestJsonTypeStringAllArms) - test(_TestJsonTypeStringI64Property) + test(_TestJSONTypeStringAllArms) + test(_TestJSONTypeStringI64Property) test(_TestDeletedResultReceiverSuccess) test(_TestDeletedResultReceiverFailure) test(_TestBoolResultReceiverSuccessTrue) @@ -64,11 +64,11 @@ actor \nodoc\ Main is TestList test(_TestSearchResultReceiverSuccess) test(_TestSearchResultReceiverConverterError) test(_TestSearchResultReceiverFailure) - test(_TestJsonRequesterGetSuccess) - test(_TestJsonRequesterGetFailure) - test(_TestJsonRequesterPostSuccess) - test(_TestJsonRequesterGetRedirect) - test(_TestJsonRequesterGetParseError) + test(_TestJSONRequesterGetSuccess) + test(_TestJSONRequesterGetFailure) + test(_TestJSONRequesterPostSuccess) + test(_TestJSONRequesterGetRedirect) + test(_TestJSONRequesterGetParseError) test(_TestNoContentDeleteSuccess) test(_TestNoContentDeleteFailure) test(_TestCheckRequester204) @@ -95,20 +95,25 @@ class \nodoc\ _TestExtractPaginationLinksNoLinks is UnitTest fun ref apply(h: TestHelper) ? => (let prev, let next) = _ExtractPaginationLinks("") - h.assert_is[None](None, prev as None, - "prev should be None") - h.assert_is[None](None, next as None, - "next should be None") + h.assert_is[None]( + None, prev as None, "prev should be None") + h.assert_is[None]( + None, next as None, "next should be None") class \nodoc\ _TestExtractPaginationLinksInvalidHeader is UnitTest fun name(): String => "extract-pagination-links/invalid-header" fun ref apply(h: TestHelper) ? => - (let prev, let next) = _ExtractPaginationLinks("not a valid link header") - h.assert_is[None](None, prev as None, + (let prev, let next) = + _ExtractPaginationLinks("not a valid link header") + h.assert_is[None]( + None, + prev as None, "prev should be None for invalid header") - h.assert_is[None](None, next as None, + h.assert_is[None]( + None, + next as None, "next should be None for invalid header") class \nodoc\ _TestExtractPaginationLinksFirstPage is UnitTest @@ -116,13 +121,18 @@ class \nodoc\ _TestExtractPaginationLinksFirstPage is UnitTest "extract-pagination-links/first-page" fun ref apply(h: TestHelper) ? => - let link = "; rel=\"next\", ; rel=\"last\"" + let link = + "; rel=\"next\", " + + "; rel=\"last\"" (let prev, let next) = _ExtractPaginationLinks(link) - h.assert_is[None](None, prev as None, - "prev should be None") + h.assert_is[None]( + None, prev as None, "prev should be None") h.assert_eq[String]( - "https://api.github.com/repositories/218833512/labels?per_page=2&page=2", + "https://api.github.com/repositories/218833512/" + + "labels?per_page=2&page=2", next as String) class \nodoc\ _TestExtractPaginationLinksLastPage is UnitTest @@ -130,26 +140,41 @@ class \nodoc\ _TestExtractPaginationLinksLastPage is UnitTest "extract-pagination-links/last-page" fun ref apply(h: TestHelper) ? => - let link = "; rel=\"prev\", ; rel=\"first\"" + let link = + "; rel=\"prev\", " + + "; rel=\"first\"" (let prev, let next) = _ExtractPaginationLinks(link) h.assert_eq[String]( - "https://api.github.com/repositories/218833512/labels?per_page=2&page=4", + "https://api.github.com/repositories/218833512/" + + "labels?per_page=2&page=4", prev as String) - h.assert_is[None](None, next as None, - "next should be None") + h.assert_is[None]( + None, next as None, "next should be None") class \nodoc\ _TestExtractPaginationLinksBetweenPages is UnitTest fun name(): String => "extract-pagination-links/between-pages" fun ref apply(h: TestHelper) ? => - let link = "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" + let link = + "; rel=\"prev\", " + + "; rel=\"next\", " + + "; rel=\"last\", " + + "; rel=\"first\"" (let prev, let next) = _ExtractPaginationLinks(link) h.assert_eq[String]( - "https://api.github.com/repositories/218833512/labels?per_page=2&page=1", + "https://api.github.com/repositories/218833512/" + + "labels?per_page=2&page=1", prev as String) h.assert_eq[String]( - "https://api.github.com/repositories/218833512/labels?per_page=2&page=3", + "https://api.github.com/repositories/218833512/" + + "labels?per_page=2&page=3", next as String) diff --git a/github_rest_api/_test_json_converters.pony b/github_rest_api/_test_json_converters.pony index b3325df..fcc6ba9 100644 --- a/github_rest_api/_test_json_converters.pony +++ b/github_rest_api/_test_json_converters.pony @@ -4,12 +4,13 @@ use "pony_test" use lori = "lori" use req = "request" -class \nodoc\ _TestGitPersonJsonConverterPreservesValues is UnitTest +class \nodoc\ _TestGitPersonJSONConverterPreservesValues is UnitTest fun name(): String => "git-person-json-converter/preserves-values" fun ref apply(h: TestHelper) ? => PonyCheck.for_all[String]( - recover val Generators.ascii_printable(1, 20) end, h)( + recover val Generators.ascii_printable(1, 20) end, + h)( {(base, h) => let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) @@ -21,7 +22,7 @@ class \nodoc\ _TestGitPersonJsonConverterPreservesValues is UnitTest .update("email", email_val) let json = JSONNav(obj) try - let person = GitPersonJsonConverter(json, creds)? + let person = GitPersonJSONConverter(json, creds)? h.assert_eq[String](name_val, person.name) h.assert_eq[String](email_val, person.email) else @@ -29,13 +30,14 @@ class \nodoc\ _TestGitPersonJsonConverterPreservesValues is UnitTest end })? -class \nodoc\ _TestGitPersonJsonConverterMissingField is UnitTest +class \nodoc\ _TestGitPersonJSONConverterMissingField is UnitTest fun name(): String => "git-person-json-converter/missing-field" fun ref apply(h: TestHelper) ? => PonyCheck.for_all2[String, USize]( recover val Generators.ascii_printable(1, 20) end, - recover val Generators.usize(0, 1) end, h)( + recover val Generators.usize(0, 1) end, + h)( {(base, skip_idx, h) => let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) @@ -45,18 +47,21 @@ class \nodoc\ _TestGitPersonJsonConverterMissingField is UnitTest if skip_idx != 1 then obj = obj.update("email", "email_" + b) end let json = JSONNav(obj) try - GitPersonJsonConverter(json, creds)? - h.fail("converter should have raised for missing field at index " - + skip_idx.string()) + GitPersonJSONConverter(json, creds)? + h.fail( + "converter should have raised " + + "for missing field at index " + + skip_idx.string()) end })? -class \nodoc\ _TestLicenseJsonConverterPreservesValues is UnitTest +class \nodoc\ _TestLicenseJSONConverterPreservesValues is UnitTest fun name(): String => "license-json-converter/preserves-values" fun ref apply(h: TestHelper) ? => PonyCheck.for_all[String]( - recover val Generators.ascii_printable(1, 20) end, h)( + recover val Generators.ascii_printable(1, 20) end, + h)( {(base, h) => let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) @@ -74,7 +79,7 @@ class \nodoc\ _TestLicenseJsonConverterPreservesValues is UnitTest .update("url", url_val) let json = JSONNav(obj) try - let license = LicenseJsonConverter(json, creds)? + let license = LicenseJSONConverter(json, creds)? h.assert_eq[String](node_id_val, license.node_id) h.assert_eq[String](name_val, license.name) h.assert_eq[String](key_val, license.key) @@ -85,13 +90,14 @@ class \nodoc\ _TestLicenseJsonConverterPreservesValues is UnitTest end })? -class \nodoc\ _TestLicenseJsonConverterMissingField is UnitTest +class \nodoc\ _TestLicenseJSONConverterMissingField is UnitTest fun name(): String => "license-json-converter/missing-field" fun ref apply(h: TestHelper) ? => PonyCheck.for_all2[String, USize]( recover val Generators.ascii_printable(1, 20) end, - recover val Generators.usize(0, 4) end, h)( + recover val Generators.usize(0, 4) end, + h)( {(base, skip_idx, h) => let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) @@ -104,18 +110,21 @@ class \nodoc\ _TestLicenseJsonConverterMissingField is UnitTest if skip_idx != 4 then obj = obj.update("url", "url_" + b) end let json = JSONNav(obj) try - LicenseJsonConverter(json, creds)? - h.fail("converter should have raised for missing field at index " - + skip_idx.string()) + LicenseJSONConverter(json, creds)? + h.fail( + "converter should have raised " + + "for missing field at index " + + skip_idx.string()) end })? -class \nodoc\ _TestCommitFileJsonConverterPreservesValues is UnitTest +class \nodoc\ _TestCommitFileJSONConverterPreservesValues is UnitTest fun name(): String => "commit-file-json-converter/preserves-values" fun ref apply(h: TestHelper) ? => PonyCheck.for_all[String]( - recover val Generators.ascii_printable(1, 20) end, h)( + recover val Generators.ascii_printable(1, 20) end, + h)( {(base, h) => let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) @@ -129,7 +138,7 @@ class \nodoc\ _TestCommitFileJsonConverterPreservesValues is UnitTest .update("filename", filename_val) let json = JSONNav(obj) try - let file = CommitFileJsonConverter(json, creds)? + let file = CommitFileJSONConverter(json, creds)? h.assert_eq[String](sha_val, file.sha) h.assert_eq[String](status_val, file.status) h.assert_eq[String](filename_val, file.filename) @@ -138,13 +147,14 @@ class \nodoc\ _TestCommitFileJsonConverterPreservesValues is UnitTest end })? -class \nodoc\ _TestCommitFileJsonConverterMissingField is UnitTest +class \nodoc\ _TestCommitFileJSONConverterMissingField is UnitTest fun name(): String => "commit-file-json-converter/missing-field" fun ref apply(h: TestHelper) ? => PonyCheck.for_all2[String, USize]( recover val Generators.ascii_printable(1, 20) end, - recover val Generators.usize(0, 2) end, h)( + recover val Generators.usize(0, 2) end, + h)( {(base, skip_idx, h) => let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) @@ -157,13 +167,15 @@ class \nodoc\ _TestCommitFileJsonConverterMissingField is UnitTest end let json = JSONNav(obj) try - CommitFileJsonConverter(json, creds)? - h.fail("converter should have raised for missing field at index " - + skip_idx.string()) + CommitFileJSONConverter(json, creds)? + h.fail( + "converter should have raised " + + "for missing field at index " + + skip_idx.string()) end })? -class \nodoc\ _TestGistChangeStatusJsonConverterPreservesValues is UnitTest +class \nodoc\ _TestGistChangeStatusJSONConverterPreservesValues is UnitTest fun name(): String => "gist-change-status-json-converter/preserves-values" @@ -171,7 +183,8 @@ class \nodoc\ _TestGistChangeStatusJsonConverterPreservesValues is UnitTest PonyCheck.for_all3[I64, I64, I64]( recover val Generators.i64() end, recover val Generators.i64() end, - recover val Generators.i64() end, h)( + recover val Generators.i64() end, + h)( {(additions, deletions, total, h) => let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) @@ -181,7 +194,7 @@ class \nodoc\ _TestGistChangeStatusJsonConverterPreservesValues is UnitTest .update("total", total) let json = JSONNav(obj) try - let status = GistChangeStatusJsonConverter(json, creds)? + let status = GistChangeStatusJSONConverter(json, creds)? h.assert_eq[I64](additions, status.additions) h.assert_eq[I64](deletions, status.deletions) h.assert_eq[I64](total, status.total) @@ -190,14 +203,15 @@ class \nodoc\ _TestGistChangeStatusJsonConverterPreservesValues is UnitTest end })? -class \nodoc\ _TestGistChangeStatusJsonConverterMissingField is UnitTest +class \nodoc\ _TestGistChangeStatusJSONConverterMissingField is UnitTest fun name(): String => "gist-change-status-json-converter/missing-field" fun ref apply(h: TestHelper) ? => PonyCheck.for_all2[I64, USize]( recover val Generators.i64() end, - recover val Generators.usize(0, 2) end, h)( + recover val Generators.usize(0, 2) end, + h)( {(value, skip_idx, h) => let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) @@ -207,13 +221,15 @@ class \nodoc\ _TestGistChangeStatusJsonConverterMissingField is UnitTest if skip_idx != 2 then obj = obj.update("total", value) end let json = JSONNav(obj) try - GistChangeStatusJsonConverter(json, creds)? - h.fail("converter should have raised for missing field at index " - + skip_idx.string()) + GistChangeStatusJSONConverter(json, creds)? + h.fail( + "converter should have raised " + + "for missing field at index " + + skip_idx.string()) end })? -primitive \nodoc\ _TestUserJson +primitive \nodoc\ _TestUserJSON """ Builds a valid User JSON object for testing converters that nest a User. """ @@ -238,7 +254,7 @@ primitive \nodoc\ _TestUserJson .update("type", "User") .update("site_admin", false) -primitive \nodoc\ _TestGitPersonJson +primitive \nodoc\ _TestGitPersonJSON """ Builds a valid GitPerson JSON object for testing converters that nest a GitPerson. @@ -248,7 +264,7 @@ primitive \nodoc\ _TestGitPersonJson .update("name", "name_" + b) .update("email", "email_" + b) -primitive \nodoc\ _TestCommitFileJson +primitive \nodoc\ _TestCommitFileJSON """ Builds a valid CommitFile JSON object for testing converters that nest a CommitFile. @@ -259,19 +275,19 @@ primitive \nodoc\ _TestCommitFileJson .update("status", "status_" + b) .update("filename", "filename_" + b) -primitive \nodoc\ _TestGitCommitJson +primitive \nodoc\ _TestGitCommitJSON """ Builds a valid GitCommit JSON object for testing converters that nest a GitCommit. """ fun apply(b: String val): JSONObject => JSONObject - .update("author", _TestGitPersonJson(b)) - .update("committer", _TestGitPersonJson(b)) + .update("author", _TestGitPersonJSON(b)) + .update("committer", _TestGitPersonJSON(b)) .update("message", "message_" + b) .update("url", "gcurl_" + b) -primitive \nodoc\ _TestLabelJson +primitive \nodoc\ _TestLabelJSON """ Builds a valid Label JSON object for testing converters that nest a Label. """ @@ -285,7 +301,7 @@ primitive \nodoc\ _TestLabelJson .update("default", false) .update("description", "ldesc_" + b) -primitive \nodoc\ _TestIssuePullRequestJson +primitive \nodoc\ _TestIssuePullRequestJSON """ Builds a valid IssuePullRequest JSON object for testing converters that nest an IssuePullRequest. @@ -298,13 +314,14 @@ primitive \nodoc\ _TestIssuePullRequestJson .update("patch_url", "prpatch_" + b) .update("merged_at", "prmerged_" + b) -class \nodoc\ _TestLabelJsonConverterPreservesValues is UnitTest +class \nodoc\ _TestLabelJSONConverterPreservesValues is UnitTest fun name(): String => "label-json-converter/preserves-values" fun ref apply(h: TestHelper) ? => PonyCheck.for_all2[String, Bool]( recover val Generators.ascii_printable(1, 20) end, - recover val Generators.bool() end, h)( + recover val Generators.bool() end, + h)( {(base, desc_is_null, h) => let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) @@ -329,7 +346,7 @@ class \nodoc\ _TestLabelJsonConverterPreservesValues is UnitTest end let json = JSONNav(obj) try - let lbl = LabelJsonConverter(json, creds)? + let lbl = LabelJSONConverter(json, creds)? h.assert_eq[I64](id_val, lbl.id) h.assert_eq[String](node_id_val, lbl.node_id) h.assert_eq[String](url_val, lbl.url) @@ -337,13 +354,13 @@ class \nodoc\ _TestLabelJsonConverterPreservesValues is UnitTest h.assert_eq[String](color_val, lbl.color) h.assert_false(lbl.default, "default should be false") if desc_is_null then - match lbl.description + match \exhaustive\ lbl.description | None => None | let _: String => h.fail("description should be None") end else - match lbl.description + match \exhaustive\ lbl.description | let s: String => h.assert_eq[String](desc_val, s) | None => @@ -355,13 +372,14 @@ class \nodoc\ _TestLabelJsonConverterPreservesValues is UnitTest end })? -class \nodoc\ _TestLabelJsonConverterMissingField is UnitTest +class \nodoc\ _TestLabelJSONConverterMissingField is UnitTest fun name(): String => "label-json-converter/missing-field" fun ref apply(h: TestHelper) ? => PonyCheck.for_all2[String, USize]( recover val Generators.ascii_printable(1, 20) end, - recover val Generators.usize(0, 6) end, h)( + recover val Generators.usize(0, 6) end, + h)( {(base, skip_idx, h) => let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) @@ -386,21 +404,23 @@ class \nodoc\ _TestLabelJsonConverterMissingField is UnitTest end let json = JSONNav(obj) try - LabelJsonConverter(json, creds)? + LabelJSONConverter(json, creds)? h.fail( - "converter should have raised for missing " - + "field at index " + skip_idx.string()) + "converter should have raised " + + "for missing field at index " + + skip_idx.string()) end })? -class \nodoc\ _TestIssuePRJsonConverterPreservesValues is UnitTest +class \nodoc\ _TestIssuePRJSONConverterPreservesValues is UnitTest fun name(): String => "issue-pull-request-json-converter/preserves-values" fun ref apply(h: TestHelper) ? => PonyCheck.for_all2[String, Bool]( recover val Generators.ascii_printable(1, 20) end, - recover val Generators.bool() end, h)( + recover val Generators.bool() end, + h)( {(base, merged_is_null, h) => let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) @@ -423,19 +443,19 @@ class \nodoc\ _TestIssuePRJsonConverterPreservesValues is UnitTest let json = JSONNav(obj) try let ipr = - IssuePullRequestJsonConverter(json, creds)? + IssuePullRequestJSONConverter(json, creds)? h.assert_eq[String](url_val, ipr.url) h.assert_eq[String](html_url_val, ipr.html_url) h.assert_eq[String](diff_url_val, ipr.diff_url) h.assert_eq[String](patch_url_val, ipr.patch_url) if merged_is_null then - match ipr.merged_at + match \exhaustive\ ipr.merged_at | None => None | let _: String => h.fail("merged_at should be None") end else - match ipr.merged_at + match \exhaustive\ ipr.merged_at | let s: String => h.assert_eq[String](merged_val, s) | None => @@ -447,14 +467,15 @@ class \nodoc\ _TestIssuePRJsonConverterPreservesValues is UnitTest end })? -class \nodoc\ _TestIssuePRJsonConverterMissingField is UnitTest +class \nodoc\ _TestIssuePRJSONConverterMissingField is UnitTest fun name(): String => "issue-pull-request-json-converter/missing-field" fun ref apply(h: TestHelper) ? => PonyCheck.for_all2[String, USize]( recover val Generators.ascii_printable(1, 20) end, - recover val Generators.usize(0, 4) end, h)( + recover val Generators.usize(0, 4) end, + h)( {(base, skip_idx, h) => let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) @@ -477,21 +498,23 @@ class \nodoc\ _TestIssuePRJsonConverterMissingField is UnitTest end let json = JSONNav(obj) try - IssuePullRequestJsonConverter(json, creds)? + IssuePullRequestJSONConverter(json, creds)? h.fail( - "converter should have raised for missing " - + "field at index " + skip_idx.string()) + "converter should have raised " + + "for missing field at index " + + skip_idx.string()) end })? -class \nodoc\ _TestAssetJsonConverterPreservesValues is UnitTest +class \nodoc\ _TestAssetJSONConverterPreservesValues is UnitTest fun name(): String => "asset-json-converter/preserves-values" fun ref apply(h: TestHelper) ? => PonyCheck.for_all2[String, Bool]( recover val Generators.ascii_printable(1, 20) end, - recover val Generators.bool() end, h)( + recover val Generators.bool() end, + h)( {(base, label_is_null, h) => let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) @@ -508,7 +531,7 @@ class \nodoc\ _TestAssetJsonConverterPreservesValues is UnitTest let ua_val: String val = "ua_" + b let url_val: String val = "url_" + b let bd_val: String val = "bd_" + b - let uploader_obj = _TestUserJson(b) + let uploader_obj = _TestUserJSON(b) var obj = JSONObject .update("id", id_val) .update("node_id", node_id_val) @@ -529,7 +552,7 @@ class \nodoc\ _TestAssetJsonConverterPreservesValues is UnitTest end let json = JSONNav(obj) try - let asset = AssetJsonConverter(json, creds)? + let asset = AssetJSONConverter(json, creds)? h.assert_eq[I64](id_val, asset.id) h.assert_eq[String](node_id_val, asset.node_id) h.assert_eq[String](name_val, asset.name) @@ -540,19 +563,19 @@ class \nodoc\ _TestAssetJsonConverterPreservesValues is UnitTest h.assert_eq[String](ca_val, asset.created_at) h.assert_eq[String](ua_val, asset.updated_at) h.assert_eq[String](url_val, asset.url) - h.assert_eq[String](bd_val, - asset.browser_download_url) - h.assert_eq[String]("login_" + b, - asset.uploader.login) + h.assert_eq[String]( + bd_val, asset.browser_download_url) + h.assert_eq[String]( + "login_" + b, asset.uploader.login) h.assert_eq[I64](I64(1), asset.uploader.id) if label_is_null then - match asset.label + match \exhaustive\ asset.label | None => None | let _: String => h.fail("label should be None") end else - match asset.label + match \exhaustive\ asset.label | let s: String => h.assert_eq[String](label_val, s) | None => @@ -564,19 +587,20 @@ class \nodoc\ _TestAssetJsonConverterPreservesValues is UnitTest end })? -class \nodoc\ _TestAssetJsonConverterMissingField is UnitTest +class \nodoc\ _TestAssetJSONConverterMissingField is UnitTest fun name(): String => "asset-json-converter/missing-field" fun ref apply(h: TestHelper) ? => PonyCheck.for_all2[String, USize]( recover val Generators.ascii_printable(1, 20) end, - recover val Generators.usize(0, 12) end, h)( + recover val Generators.usize(0, 12) end, + h)( {(base, skip_idx, h) => let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) let b: String val = base.clone() - let uploader_obj = _TestUserJson(b) + let uploader_obj = _TestUserJSON(b) var obj = JSONObject if skip_idx != 0 then obj = obj.update("id", I64(42)) @@ -615,26 +639,29 @@ class \nodoc\ _TestAssetJsonConverterMissingField is UnitTest obj = obj.update("url", "url_" + b) end if skip_idx != 12 then - obj = obj.update( - "browser_download_url", "bd_" + b) + obj = + obj.update( + "browser_download_url", "bd_" + b) end let json = JSONNav(obj) try - AssetJsonConverter(json, creds)? + AssetJSONConverter(json, creds)? h.fail( - "converter should have raised for missing " - + "field at index " + skip_idx.string()) + "converter should have raised " + + "for missing field at index " + + skip_idx.string()) end })? -class \nodoc\ _TestGistFileJsonConverterPreservesValues is UnitTest +class \nodoc\ _TestGistFileJSONConverterPreservesValues is UnitTest fun name(): String => "gist-file-json-converter/preserves-values" fun ref apply(h: TestHelper) ? => PonyCheck.for_all2[String, Bool]( recover val Generators.ascii_printable(1, 20) end, - recover val Generators.bool() end, h)( + recover val Generators.bool() end, + h)( {(base, lang_is_null, h) => let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) @@ -661,37 +688,37 @@ class \nodoc\ _TestGistFileJsonConverterPreservesValues is UnitTest end let json = JSONNav(obj) try - let gf = GistFileJsonConverter(json, creds)? + let gf = GistFileJSONConverter(json, creds)? h.assert_eq[String](fn_val, gf.filename) h.assert_eq[String](ct_val, gf.content_type) h.assert_eq[String](raw_val, gf.raw_url) h.assert_eq[I64](size_val, gf.size) - match gf.content + match \exhaustive\ gf.content | let s: String => h.assert_eq[String](content_val, s) | None => h.fail("content should be String") end - match gf.encoding + match \exhaustive\ gf.encoding | let s: String => h.assert_eq[String](encoding_val, s) | None => h.fail("encoding should be String") end - match gf.truncated + match \exhaustive\ gf.truncated | let t: Bool => h.assert_false(t, "truncated should be false") | None => h.fail("truncated should be Bool") end if lang_is_null then - match gf.language + match \exhaustive\ gf.language | None => None | let _: String => h.fail("language should be None") end else - match gf.language + match \exhaustive\ gf.language | let s: String => h.assert_eq[String](lang_val, s) | None => @@ -703,14 +730,15 @@ class \nodoc\ _TestGistFileJsonConverterPreservesValues is UnitTest end })? -class \nodoc\ _TestGistFileJsonConverterMissingField is UnitTest +class \nodoc\ _TestGistFileJSONConverterMissingField is UnitTest fun name(): String => "gist-file-json-converter/missing-field" fun ref apply(h: TestHelper) ? => PonyCheck.for_all2[String, USize]( recover val Generators.ascii_printable(1, 20) end, - recover val Generators.usize(0, 4) end, h)( + recover val Generators.usize(0, 4) end, + h)( {(base, skip_idx, h) => let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) @@ -733,20 +761,22 @@ class \nodoc\ _TestGistFileJsonConverterMissingField is UnitTest end let json = JSONNav(obj) try - GistFileJsonConverter(json, creds)? + GistFileJSONConverter(json, creds)? h.fail( - "converter should have raised for missing " - + "field at index " + skip_idx.string()) + "converter should have raised " + + "for missing field at index " + + skip_idx.string()) end })? -class \nodoc\ _TestGistFileJsonConverterAbsentOptionalFields is UnitTest +class \nodoc\ _TestGistFileJSONConverterAbsentOptionalFields is UnitTest fun name(): String => "gist-file-json-converter/absent-optional-fields" fun ref apply(h: TestHelper) ? => PonyCheck.for_all[String]( - recover val Generators.ascii_printable(1, 20) end, h)( + recover val Generators.ascii_printable(1, 20) end, + h)( {(base, h) => let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) @@ -759,21 +789,21 @@ class \nodoc\ _TestGistFileJsonConverterAbsentOptionalFields is UnitTest .update("size", I64(100)) let json = JSONNav(obj) try - let gf = GistFileJsonConverter(json, creds)? + let gf = GistFileJSONConverter(json, creds)? h.assert_eq[String]("fn_" + b, gf.filename) h.assert_eq[String]("ct_" + b, gf.content_type) h.assert_eq[I64](I64(100), gf.size) - match gf.content + match \exhaustive\ gf.content | None => None | let _: String => h.fail("content should be None") end - match gf.encoding + match \exhaustive\ gf.encoding | None => None | let _: String => h.fail("encoding should be None") end - match gf.truncated + match \exhaustive\ gf.truncated | None => None | let _: Bool => h.fail("truncated should be None") @@ -783,13 +813,14 @@ class \nodoc\ _TestGistFileJsonConverterAbsentOptionalFields is UnitTest end })? -class \nodoc\ _TestGitCommitJsonConverterPreservesValues is UnitTest +class \nodoc\ _TestGitCommitJSONConverterPreservesValues is UnitTest fun name(): String => "git-commit-json-converter/preserves-values" fun ref apply(h: TestHelper) ? => PonyCheck.for_all[String]( - recover val Generators.ascii_printable(1, 20) end, h)( + recover val Generators.ascii_printable(1, 20) end, + h)( {(base, h) => let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) @@ -797,20 +828,21 @@ class \nodoc\ _TestGitCommitJsonConverterPreservesValues is UnitTest let message_val: String val = "message_" + b let url_val: String val = "gcurl_" + b let obj = JSONObject - .update("author", _TestGitPersonJson(b)) - .update("committer", _TestGitPersonJson(b)) + .update("author", _TestGitPersonJSON(b)) + .update("committer", _TestGitPersonJSON(b)) .update("message", message_val) .update("url", url_val) let json = JSONNav(obj) try - let gc = GitCommitJsonConverter(json, creds)? - h.assert_eq[String]("name_" + b, gc.author.name) - h.assert_eq[String]("email_" + b, - gc.author.email) - h.assert_eq[String]("name_" + b, - gc.committer.name) - h.assert_eq[String]("email_" + b, - gc.committer.email) + let gc = GitCommitJSONConverter(json, creds)? + h.assert_eq[String]( + "name_" + b, gc.author.name) + h.assert_eq[String]( + "email_" + b, gc.author.email) + h.assert_eq[String]( + "name_" + b, gc.committer.name) + h.assert_eq[String]( + "email_" + b, gc.committer.email) h.assert_eq[String](message_val, gc.message) h.assert_eq[String](url_val, gc.url) else @@ -818,26 +850,29 @@ class \nodoc\ _TestGitCommitJsonConverterPreservesValues is UnitTest end })? -class \nodoc\ _TestGitCommitJsonConverterMissingField is UnitTest +class \nodoc\ _TestGitCommitJSONConverterMissingField is UnitTest fun name(): String => "git-commit-json-converter/missing-field" fun ref apply(h: TestHelper) ? => PonyCheck.for_all2[String, USize]( recover val Generators.ascii_printable(1, 20) end, - recover val Generators.usize(0, 3) end, h)( + recover val Generators.usize(0, 3) end, + h)( {(base, skip_idx, h) => let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) let b: String val = base.clone() var obj = JSONObject if skip_idx != 0 then - obj = obj.update("author", - _TestGitPersonJson(b)) + obj = + obj.update( + "author", _TestGitPersonJSON(b)) end if skip_idx != 1 then - obj = obj.update("committer", - _TestGitPersonJson(b)) + obj = + obj.update( + "committer", _TestGitPersonJSON(b)) end if skip_idx != 2 then obj = obj.update("message", "message_" + b) @@ -847,20 +882,22 @@ class \nodoc\ _TestGitCommitJsonConverterMissingField is UnitTest end let json = JSONNav(obj) try - GitCommitJsonConverter(json, creds)? + GitCommitJSONConverter(json, creds)? h.fail( - "converter should have raised for missing " - + "field at index " + skip_idx.string()) + "converter should have raised " + + "for missing field at index " + + skip_idx.string()) end })? -class \nodoc\ _TestCommitJsonConverterPreservesValues is UnitTest +class \nodoc\ _TestCommitJSONConverterPreservesValues is UnitTest fun name(): String => "commit-json-converter/preserves-values" fun ref apply(h: TestHelper) ? => PonyCheck.for_all[String]( - recover val Generators.ascii_printable(1, 20) end, h)( + recover val Generators.ascii_printable(1, 20) end, + h)( {(base, h) => let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) @@ -871,54 +908,57 @@ class \nodoc\ _TestCommitJsonConverterPreservesValues is UnitTest let comments_url_val: String val = "curl_" + b let obj = JSONObject .update("sha", sha_val) - .update("files", - JSONArray.push(_TestCommitFileJson(b))) - .update("commit", _TestGitCommitJson(b)) + .update( + "files", + JSONArray.push(_TestCommitFileJSON(b))) + .update("commit", _TestGitCommitJSON(b)) .update("url", url_val) .update("html_url", html_url_val) .update("comments_url", comments_url_val) let json = JSONNav(obj) try - let c = CommitJsonConverter(json, creds)? + let c = CommitJSONConverter(json, creds)? h.assert_eq[String](sha_val, c.sha) h.assert_eq[USize](1, c.files.size()) try - h.assert_eq[String]("sha_" + b, - c.files(0)?.sha) - h.assert_eq[String]("status_" + b, - c.files(0)?.status) - h.assert_eq[String]("filename_" + b, - c.files(0)?.filename) + h.assert_eq[String]( + "sha_" + b, c.files(0)?.sha) + h.assert_eq[String]( + "status_" + b, c.files(0)?.status) + h.assert_eq[String]( + "filename_" + b, c.files(0)?.filename) else h.fail( "files array access raised an error") end - h.assert_eq[String]("name_" + b, - c.git_commit.author.name) - h.assert_eq[String]("email_" + b, + h.assert_eq[String]( + "name_" + b, c.git_commit.author.name) + h.assert_eq[String]( + "email_" + b, c.git_commit.author.email) - h.assert_eq[String]("message_" + b, - c.git_commit.message) - h.assert_eq[String]("gcurl_" + b, - c.git_commit.url) + h.assert_eq[String]( + "message_" + b, c.git_commit.message) + h.assert_eq[String]( + "gcurl_" + b, c.git_commit.url) h.assert_eq[String](url_val, c.url) - h.assert_eq[String](html_url_val, - c.html_url) - h.assert_eq[String](comments_url_val, - c.comments_url) + h.assert_eq[String]( + html_url_val, c.html_url) + h.assert_eq[String]( + comments_url_val, c.comments_url) else h.fail("converter raised an error") end })? -class \nodoc\ _TestCommitJsonConverterMissingField is UnitTest +class \nodoc\ _TestCommitJSONConverterMissingField is UnitTest fun name(): String => "commit-json-converter/missing-field" fun ref apply(h: TestHelper) ? => PonyCheck.for_all2[String, USize]( recover val Generators.ascii_printable(1, 20) end, - recover val Generators.usize(0, 5) end, h)( + recover val Generators.usize(0, 5) end, + h)( {(base, skip_idx, h) => let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) @@ -928,33 +968,40 @@ class \nodoc\ _TestCommitJsonConverterMissingField is UnitTest obj = obj.update("sha", "sha_" + b) end if skip_idx != 1 then - obj = obj.update("files", - JSONArray.push(_TestCommitFileJson(b))) + obj = + obj.update( + "files", + JSONArray.push( + _TestCommitFileJSON(b))) end if skip_idx != 2 then - obj = obj.update("commit", - _TestGitCommitJson(b)) + obj = + obj.update( + "commit", _TestGitCommitJSON(b)) end if skip_idx != 3 then obj = obj.update("url", "url_" + b) end if skip_idx != 4 then - obj = obj.update("html_url", "html_" + b) + obj = + obj.update("html_url", "html_" + b) end if skip_idx != 5 then - obj = obj.update("comments_url", - "curl_" + b) + obj = + obj.update( + "comments_url", "curl_" + b) end let json = JSONNav(obj) try - CommitJsonConverter(json, creds)? + CommitJSONConverter(json, creds)? h.fail( - "converter should have raised for missing " - + "field at index " + skip_idx.string()) + "converter should have raised " + + "for missing field at index " + + skip_idx.string()) end })? -class \nodoc\ _TestIssueJsonConverterPreservesValues is UnitTest +class \nodoc\ _TestIssueJSONConverterPreservesValues is UnitTest fun name(): String => "issue-json-converter/preserves-values" @@ -962,7 +1009,8 @@ class \nodoc\ _TestIssueJsonConverterPreservesValues is UnitTest PonyCheck.for_all3[String, Bool, Bool]( recover val Generators.ascii_printable(1, 20) end, recover val Generators.bool() end, - recover val Generators.bool() end, h)( + recover val Generators.bool() end, + h)( {(base, state_is_null, body_is_null, h) => let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) @@ -986,11 +1034,13 @@ class \nodoc\ _TestIssueJsonConverterPreservesValues is UnitTest .update("html_url", html_url_val) .update("number", number_val) .update("title", title_val) - .update("user", _TestUserJson(b)) - .update("labels", - JSONArray.push(_TestLabelJson(b))) - .update("pull_request", - _TestIssuePullRequestJson(b)) + .update("user", _TestUserJSON(b)) + .update( + "labels", + JSONArray.push(_TestLabelJSON(b))) + .update( + "pull_request", + _TestIssuePullRequestJSON(b)) if state_is_null then obj = obj.update("state", None) else @@ -1004,38 +1054,38 @@ class \nodoc\ _TestIssueJsonConverterPreservesValues is UnitTest let json = JSONNav(obj) try let issue = - IssueJsonConverter(json, creds)? + IssueJSONConverter(json, creds)? h.assert_eq[String](url_val, issue.url) - h.assert_eq[String](repo_url_val, - issue.respository_url) - h.assert_eq[String](labels_url_val, - issue.labels_url) - h.assert_eq[String](cmnts_url_val, - issue.comments_url) - h.assert_eq[String](events_url_val, - issue.events_url) - h.assert_eq[String](html_url_val, - issue.html_url) + h.assert_eq[String]( + repo_url_val, issue.respository_url) + h.assert_eq[String]( + labels_url_val, issue.labels_url) + h.assert_eq[String]( + cmnts_url_val, issue.comments_url) + h.assert_eq[String]( + events_url_val, issue.events_url) + h.assert_eq[String]( + html_url_val, issue.html_url) h.assert_eq[I64](number_val, issue.number) h.assert_eq[String](title_val, issue.title) - h.assert_eq[String]("login_" + b, - issue.user.login) + h.assert_eq[String]( + "login_" + b, issue.user.login) h.assert_eq[USize](1, issue.labels.size()) try - h.assert_eq[String]("lname_" + b, - issue.labels(0)?.name) + h.assert_eq[String]( + "lname_" + b, issue.labels(0)?.name) else h.fail( "labels array access raised an error") end if state_is_null then - match issue.state + match \exhaustive\ issue.state | None => None | let _: String => h.fail("state should be None") end else - match issue.state + match \exhaustive\ issue.state | let s: String => h.assert_eq[String](state_val, s) | None => @@ -1043,25 +1093,25 @@ class \nodoc\ _TestIssueJsonConverterPreservesValues is UnitTest end end if body_is_null then - match issue.body + match \exhaustive\ issue.body | None => None | let _: String => h.fail("body should be None") end else - match issue.body + match \exhaustive\ issue.body | let s: String => h.assert_eq[String](body_val, s) | None => h.fail("body should be String") end end - match issue.pull_request + match \exhaustive\ issue.pull_request | let pr: IssuePullRequest => - h.assert_eq[String]("prurl_" + b, - pr.url) - h.assert_eq[String]("prhtml_" + b, - pr.html_url) + h.assert_eq[String]( + "prurl_" + b, pr.url) + h.assert_eq[String]( + "prhtml_" + b, pr.html_url) | None => h.fail( "pull_request should be present") @@ -1071,7 +1121,7 @@ class \nodoc\ _TestIssueJsonConverterPreservesValues is UnitTest end })? -primitive \nodoc\ _TestLicenseJson +primitive \nodoc\ _TestLicenseJSON """ Builds a valid License JSON object for testing converters that nest a License. @@ -1084,7 +1134,7 @@ primitive \nodoc\ _TestLicenseJson .update("spdx_id", "licspdx_" + b) .update("url", "licurl_" + b) -primitive \nodoc\ _TestGistFileJson +primitive \nodoc\ _TestGistFileJSON """ Builds a fully-populated GistFile JSON object for testing converters that nest a GistFile. Includes all optional fields @@ -1101,10 +1151,10 @@ primitive \nodoc\ _TestGistFileJson .update("encoding", "utf-8") .update("truncated", false) -primitive \nodoc\ _TestRepositoryJson +primitive \nodoc\ _TestRepositoryJSON """ Builds a complete valid Repository JSON object for testing - RepositoryJsonConverter. Includes all required and optional + RepositoryJSONConverter. Includes all required and optional fields with non-null values. """ fun apply(b: String val): JSONObject => @@ -1114,7 +1164,7 @@ primitive \nodoc\ _TestRepositoryJson .update("name", "rname_" + b) .update("full_name", "rfull_" + b) .update("description", "rdesc_" + b) - .update("owner", _TestUserJson(b)) + .update("owner", _TestUserJSON(b)) .update("private", false) .update("fork", false) .update("created_at", "rca_" + b) @@ -1122,7 +1172,7 @@ primitive \nodoc\ _TestRepositoryJson .update("updated_at", "rua_" + b) .update("homepage", "rhome_" + b) .update("default_branch", "rdb_" + b) - .update("organization", _TestUserJson(b)) + .update("organization", _TestUserJSON(b)) .update("size", I64(100)) .update("forks", I64(5)) .update("forks_count", I64(5)) @@ -1134,7 +1184,7 @@ primitive \nodoc\ _TestRepositoryJson .update("watchers", I64(50)) .update("watchers_count", I64(50)) .update("language", "rlang_" + b) - .update("license", _TestLicenseJson(b)) + .update("license", _TestLicenseJSON(b)) .update("archived", false) .update("disabled", false) .update("has_downloads", true) @@ -1174,7 +1224,8 @@ primitive \nodoc\ _TestRepositoryJson .update("stargazers_url", "rstargazers_" + b) .update("statuses_url", "rstatuses_" + b) .update("subscribers_url", "rsubs_" + b) - .update("subscription_url", + .update( + "subscription_url", "rsubscription_" + b) .update("tags_url", "rtags_" + b) .update("trees_url", "rtrees_" + b) @@ -1184,10 +1235,10 @@ primitive \nodoc\ _TestRepositoryJson .update("ssh_url", "rssh_" + b) .update("svn_url", "rsvn_" + b) -primitive \nodoc\ _TestGistJson +primitive \nodoc\ _TestGistJSON """ Builds a complete valid Gist JSON object for testing - GistJsonConverter. Sets comments_enabled to false (not the + GistJSONConverter. Sets comments_enabled to false (not the default) so preserves-values can verify the explicit value and absent-optional can verify the default. """ @@ -1197,11 +1248,12 @@ primitive \nodoc\ _TestGistJson .update("node_id", "gnid_" + b) .update("description", "gdesc_" + b) .update("public", true) - .update("owner", _TestUserJson(b)) - .update("user", _TestUserJson(b)) - .update("files", + .update("owner", _TestUserJSON(b)) + .update("user", _TestUserJSON(b)) + .update( + "files", JSONObject.update( - "file1_" + b, _TestGistFileJson(b))) + "file1_" + b, _TestGistFileJSON(b))) .update("comments", I64(5)) .update("comments_enabled", false) .update("truncated", false) @@ -1215,14 +1267,15 @@ primitive \nodoc\ _TestGistJson .update("git_pull_url", "gpullurl_" + b) .update("git_push_url", "gpushurl_" + b) -class \nodoc\ _TestIssueJsonConverterMissingField is UnitTest +class \nodoc\ _TestIssueJSONConverterMissingField is UnitTest fun name(): String => "issue-json-converter/missing-field" fun ref apply(h: TestHelper) ? => PonyCheck.for_all2[String, USize]( recover val Generators.ascii_printable(1, 20) end, - recover val Generators.usize(0, 11) end, h)( + recover val Generators.usize(0, 11) end, + h)( {(base, skip_idx, h) => let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) @@ -1232,20 +1285,24 @@ class \nodoc\ _TestIssueJsonConverterMissingField is UnitTest obj = obj.update("url", "url_" + b) end if skip_idx != 1 then - obj = obj.update("repository_url", - "rurl_" + b) + obj = + obj.update( + "repository_url", "rurl_" + b) end if skip_idx != 2 then - obj = obj.update("labels_url", - "lsurl_" + b) + obj = + obj.update( + "labels_url", "lsurl_" + b) end if skip_idx != 3 then - obj = obj.update("comments_url", - "curl_" + b) + obj = + obj.update( + "comments_url", "curl_" + b) end if skip_idx != 4 then - obj = obj.update("events_url", - "evurl_" + b) + obj = + obj.update( + "events_url", "evurl_" + b) end if skip_idx != 5 then obj = obj.update("html_url", "html_" + b) @@ -1257,7 +1314,7 @@ class \nodoc\ _TestIssueJsonConverterMissingField is UnitTest obj = obj.update("title", "title_" + b) end if skip_idx != 8 then - obj = obj.update("user", _TestUserJson(b)) + obj = obj.update("user", _TestUserJSON(b)) end if skip_idx != 9 then obj = obj.update("state", "open") @@ -1266,25 +1323,29 @@ class \nodoc\ _TestIssueJsonConverterMissingField is UnitTest obj = obj.update("body", "body_" + b) end if skip_idx != 11 then - obj = obj.update("labels", - JSONArray.push(_TestLabelJson(b))) + obj = + obj.update( + "labels", + JSONArray.push(_TestLabelJSON(b))) end let json = JSONNav(obj) try - IssueJsonConverter(json, creds)? + IssueJSONConverter(json, creds)? h.fail( - "converter should have raised for missing " - + "field at index " + skip_idx.string()) + "converter should have raised " + + "for missing field at index " + + skip_idx.string()) end })? -class \nodoc\ _TestIssueJsonConverterAbsentPullRequest is UnitTest +class \nodoc\ _TestIssueJSONConverterAbsentPullRequest is UnitTest fun name(): String => "issue-json-converter/absent-pull-request" fun ref apply(h: TestHelper) ? => PonyCheck.for_all[String]( - recover val Generators.ascii_printable(1, 20) end, h)( + recover val Generators.ascii_printable(1, 20) end, + h)( {(base, h) => let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) @@ -1298,16 +1359,17 @@ class \nodoc\ _TestIssueJsonConverterAbsentPullRequest is UnitTest .update("html_url", "html_" + b) .update("number", I64(42)) .update("title", "title_" + b) - .update("user", _TestUserJson(b)) + .update("user", _TestUserJSON(b)) .update("state", "open") .update("body", "body_" + b) - .update("labels", - JSONArray.push(_TestLabelJson(b))) + .update( + "labels", + JSONArray.push(_TestLabelJSON(b))) let json = JSONNav(obj) try let issue = - IssueJsonConverter(json, creds)? - match issue.pull_request + IssueJSONConverter(json, creds)? + match \exhaustive\ issue.pull_request | None => None | let _: IssuePullRequest => h.fail( @@ -1318,7 +1380,7 @@ class \nodoc\ _TestIssueJsonConverterAbsentPullRequest is UnitTest end })? -class \nodoc\ _TestRepoJsonConverterPreservesValues +class \nodoc\ _TestRepoJSONConverterPreservesValues is UnitTest fun name(): String => "repo-json-converter/preserves-values" @@ -1326,12 +1388,13 @@ class \nodoc\ _TestRepoJsonConverterPreservesValues fun ref apply(h: TestHelper) ? => PonyCheck.for_all2[String, USize]( recover val Generators.ascii_printable(1, 20) end, - recover val Generators.usize(0, 15) end, h)( + recover val Generators.usize(0, 15) end, + h)( {(base, mask, h) => let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) let b: String val = base.clone() - var obj = _TestRepositoryJson(b) + var obj = _TestRepositoryJSON(b) if (mask and 1) != 0 then obj = obj.update("description", None) end @@ -1347,23 +1410,23 @@ class \nodoc\ _TestRepoJsonConverterPreservesValues let json = JSONNav(obj) try let repo = - RepositoryJsonConverter(json, creds)? + RepositoryJSONConverter(json, creds)? h.assert_eq[I64](I64(1), repo.id) - h.assert_eq[String]("rnid_" + b, - repo.node_id) - h.assert_eq[String]("rname_" + b, - repo.name) - h.assert_eq[String]("rfull_" + b, - repo.full_name) + h.assert_eq[String]( + "rnid_" + b, repo.node_id) + h.assert_eq[String]( + "rname_" + b, repo.name) + h.assert_eq[String]( + "rfull_" + b, repo.full_name) if (mask and 1) != 0 then - match repo.description + match \exhaustive\ repo.description | None => None | let _: String => h.fail( "description should be None") end else - match repo.description + match \exhaustive\ repo.description | let s: String => h.assert_eq[String]( "rdesc_" + b, s) @@ -1372,26 +1435,28 @@ class \nodoc\ _TestRepoJsonConverterPreservesValues "description should be String") end end - h.assert_eq[String]("login_" + b, - repo.owner.login) - h.assert_false(repo.private, + h.assert_eq[String]( + "login_" + b, repo.owner.login) + h.assert_false( + repo.private, "private should be false") - h.assert_false(repo.fork, + h.assert_false( + repo.fork, "fork should be false") - h.assert_eq[String]("rca_" + b, - repo.created_at) - h.assert_eq[String]("rpa_" + b, - repo.pushed_at) - h.assert_eq[String]("rua_" + b, - repo.updated_at) + h.assert_eq[String]( + "rca_" + b, repo.created_at) + h.assert_eq[String]( + "rpa_" + b, repo.pushed_at) + h.assert_eq[String]( + "rua_" + b, repo.updated_at) if (mask and 2) != 0 then - match repo.homepage + match \exhaustive\ repo.homepage | None => None | let _: String => h.fail("homepage should be None") end else - match repo.homepage + match \exhaustive\ repo.homepage | let s: String => h.assert_eq[String]( "rhome_" + b, s) @@ -1400,53 +1465,53 @@ class \nodoc\ _TestRepoJsonConverterPreservesValues "homepage should be String") end end - h.assert_eq[String]("rdb_" + b, - repo.default_branch) - match repo.organization + h.assert_eq[String]( + "rdb_" + b, repo.default_branch) + match \exhaustive\ repo.organization | let u: User => - h.assert_eq[String]("login_" + b, - u.login) + h.assert_eq[String]( + "login_" + b, u.login) | None => h.fail( "organization should be present") end h.assert_eq[I64](I64(100), repo.size) h.assert_eq[I64](I64(5), repo.forks) - h.assert_eq[I64](I64(5), - repo.forks_count) - match repo.network_count + h.assert_eq[I64]( + I64(5), repo.forks_count) + match \exhaustive\ repo.network_count | let n: I64 => h.assert_eq[I64](I64(10), n) | None => h.fail( "network_count should be present") end - h.assert_eq[I64](I64(3), - repo.open_issues) - h.assert_eq[I64](I64(3), - repo.open_issues_count) - h.assert_eq[I64](I64(50), - repo.stargazers_count) - match repo.subscribers_count + h.assert_eq[I64]( + I64(3), repo.open_issues) + h.assert_eq[I64]( + I64(3), repo.open_issues_count) + h.assert_eq[I64]( + I64(50), repo.stargazers_count) + match \exhaustive\ repo.subscribers_count | let n: I64 => h.assert_eq[I64](I64(20), n) | None => h.fail( - "subscribers_count should be " - + "present") + "subscribers_count should be " + + "present") end - h.assert_eq[I64](I64(50), - repo.watchers) - h.assert_eq[I64](I64(50), - repo.watchers_count) + h.assert_eq[I64]( + I64(50), repo.watchers) + h.assert_eq[I64]( + I64(50), repo.watchers_count) if (mask and 4) != 0 then - match repo.language + match \exhaustive\ repo.language | None => None | let _: String => h.fail("language should be None") end else - match repo.language + match \exhaustive\ repo.language | let s: String => h.assert_eq[String]( "rlang_" + b, s) @@ -1455,31 +1520,38 @@ class \nodoc\ _TestRepoJsonConverterPreservesValues "language should be String") end end - match repo.license + match \exhaustive\ repo.license | let l: License => h.assert_eq[String]( "lickey_" + b, l.key) | None => h.fail("license should be present") end - h.assert_false(repo.archived, + h.assert_false( + repo.archived, "archived should be false") - h.assert_false(repo.disabled, + h.assert_false( + repo.disabled, "disabled should be false") - h.assert_true(repo.has_downloads, + h.assert_true( + repo.has_downloads, "has_downloads should be true") - h.assert_true(repo.has_issues, + h.assert_true( + repo.has_issues, "has_issues should be true") - h.assert_false(repo.has_pages, + h.assert_false( + repo.has_pages, "has_pages should be false") - h.assert_true(repo.has_projects, + h.assert_true( + repo.has_projects, "has_projects should be true") - h.assert_true(repo.has_wiki, + h.assert_true( + repo.has_wiki, "has_wiki should be true") - h.assert_eq[String]("rurl_" + b, - repo.url) - h.assert_eq[String]("rhurl_" + b, - repo.html_url) + h.assert_eq[String]( + "rurl_" + b, repo.url) + h.assert_eq[String]( + "rhurl_" + b, repo.html_url) h.assert_eq[String]( "rarchive_" + b, repo.archive_url) @@ -1575,14 +1647,14 @@ class \nodoc\ _TestRepoJsonConverterPreservesValues h.assert_eq[String]( "rgit_" + b, repo.git_url) if (mask and 8) != 0 then - match repo.mirror_url + match \exhaustive\ repo.mirror_url | None => None | let _: String => h.fail( "mirror_url should be None") end else - match repo.mirror_url + match \exhaustive\ repo.mirror_url | let s: String => h.assert_eq[String]( "rmirror_" + b, s) @@ -1600,7 +1672,7 @@ class \nodoc\ _TestRepoJsonConverterPreservesValues end })? -class \nodoc\ _TestRepoJsonConverterMissingField +class \nodoc\ _TestRepoJSONConverterMissingField is UnitTest fun name(): String => "repo-json-converter/missing-field" @@ -1660,18 +1732,18 @@ class \nodoc\ _TestRepoJsonConverterMissingField let creds = req.Credentials(auth) let b: String val = base.clone() try - let obj = _TestRepositoryJson(b) + let obj = _TestRepositoryJSON(b) .remove(required(skip_idx)?) let json = JSONNav(obj) - RepositoryJsonConverter(json, creds)? + RepositoryJSONConverter(json, creds)? h.fail( - "converter should have raised for " - + "missing field at index " - + skip_idx.string()) + "converter should have raised for " + + "missing field at index " + + skip_idx.string()) end })? -class \nodoc\ _TestRepoJsonConverterAbsentOptionalFields +class \nodoc\ _TestRepoJSONConverterAbsentOptionalFields is UnitTest fun name(): String => "repo-json-converter/absent-optional-fields" @@ -1685,7 +1757,7 @@ class \nodoc\ _TestRepoJsonConverterAbsentOptionalFields let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) let b: String val = base.clone() - let obj = _TestRepositoryJson(b) + let obj = _TestRepositoryJSON(b) .remove("organization") .remove("license") .remove("network_count") @@ -1693,42 +1765,42 @@ class \nodoc\ _TestRepoJsonConverterAbsentOptionalFields let json = JSONNav(obj) try let repo = - RepositoryJsonConverter(json, creds)? - match repo.organization + RepositoryJSONConverter(json, creds)? + match \exhaustive\ repo.organization | None => None | let _: User => h.fail( "organization should be None") end - match repo.license + match \exhaustive\ repo.license | None => None | let _: License => h.fail("license should be None") end - match repo.network_count + match \exhaustive\ repo.network_count | None => None | let _: I64 => h.fail( "network_count should be None") end - match repo.subscribers_count + match \exhaustive\ repo.subscribers_count | None => None | let _: I64 => h.fail( - "subscribers_count should be " - + "None") + "subscribers_count should be " + + "None") end - h.assert_eq[String]("rname_" + b, - repo.name) + h.assert_eq[String]( + "rname_" + b, repo.name) h.assert_eq[I64](I64(1), repo.id) - h.assert_eq[String]("rurl_" + b, - repo.url) + h.assert_eq[String]( + "rurl_" + b, repo.url) else h.fail("converter raised an error") end })? -class \nodoc\ _TestGistJsonConverterPreservesValues +class \nodoc\ _TestGistJSONConverterPreservesValues is UnitTest fun name(): String => "gist-json-converter/preserves-values" @@ -1738,32 +1810,33 @@ class \nodoc\ _TestGistJsonConverterPreservesValues recover val Generators.ascii_printable(1, 20) end, - recover val Generators.bool() end, h)( + recover val Generators.bool() end, + h)( {(base, desc_is_null, h) => let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) let b: String val = base.clone() - var obj = _TestGistJson(b) + var obj = _TestGistJSON(b) if desc_is_null then obj = obj.update("description", None) end let json = JSONNav(obj) try let gist = - GistJsonConverter(json, creds)? - h.assert_eq[String]("gid_" + b, - gist.id) - h.assert_eq[String]("gnid_" + b, - gist.node_id) + GistJSONConverter(json, creds)? + h.assert_eq[String]( + "gid_" + b, gist.id) + h.assert_eq[String]( + "gnid_" + b, gist.node_id) if desc_is_null then - match gist.description + match \exhaustive\ gist.description | None => None | let _: String => h.fail( "description should be None") end else - match gist.description + match \exhaustive\ gist.description | let s: String => h.assert_eq[String]( "gdesc_" + b, s) @@ -1772,10 +1845,11 @@ class \nodoc\ _TestGistJsonConverterPreservesValues "description should be String") end end - h.assert_true(gist.public, + h.assert_true( + gist.public, "public should be true") - h.assert_eq[USize](1, - gist.files.size()) + h.assert_eq[USize]( + 1, gist.files.size()) try h.assert_eq[String]( "file1_" + b, @@ -1787,21 +1861,22 @@ class \nodoc\ _TestGistJsonConverterPreservesValues h.fail( "files array access raised error") end - h.assert_eq[I64](I64(5), - gist.comments) + h.assert_eq[I64]( + I64(5), gist.comments) h.assert_false( gist.comments_enabled, "comments_enabled should be false") - h.assert_false(gist.truncated, + h.assert_false( + gist.truncated, "truncated should be false") - h.assert_eq[String]("gca_" + b, - gist.created_at) - h.assert_eq[String]("gua_" + b, - gist.updated_at) - h.assert_eq[String]("gurl_" + b, - gist.url) - h.assert_eq[String]("ghurl_" + b, - gist.html_url) + h.assert_eq[String]( + "gca_" + b, gist.created_at) + h.assert_eq[String]( + "gua_" + b, gist.updated_at) + h.assert_eq[String]( + "gurl_" + b, gist.url) + h.assert_eq[String]( + "ghurl_" + b, gist.html_url) h.assert_eq[String]( "gforksurl_" + b, gist.forks_url) @@ -1817,17 +1892,17 @@ class \nodoc\ _TestGistJsonConverterPreservesValues h.assert_eq[String]( "gpushurl_" + b, gist.git_push_url) - match gist.owner + match \exhaustive\ gist.owner | let u: User => - h.assert_eq[String]("login_" + b, - u.login) + h.assert_eq[String]( + "login_" + b, u.login) | None => h.fail("owner should be present") end - match gist.user + match \exhaustive\ gist.user | let u: User => - h.assert_eq[String]("login_" + b, - u.login) + h.assert_eq[String]( + "login_" + b, u.login) | None => h.fail("user should be present") end @@ -1836,7 +1911,7 @@ class \nodoc\ _TestGistJsonConverterPreservesValues end })? -class \nodoc\ _TestGistJsonConverterMissingField +class \nodoc\ _TestGistJSONConverterMissingField is UnitTest fun name(): String => "gist-json-converter/missing-field" @@ -1866,18 +1941,18 @@ class \nodoc\ _TestGistJsonConverterMissingField let creds = req.Credentials(auth) let b: String val = base.clone() try - let obj = _TestGistJson(b) + let obj = _TestGistJSON(b) .remove(required(skip_idx)?) let json = JSONNav(obj) - GistJsonConverter(json, creds)? + GistJSONConverter(json, creds)? h.fail( - "converter should have raised for " - + "missing field at index " - + skip_idx.string()) + "converter should have raised for " + + "missing field at index " + + skip_idx.string()) end })? -class \nodoc\ _TestGistJsonConverterAbsentOptionalFields +class \nodoc\ _TestGistJSONConverterAbsentOptionalFields is UnitTest fun name(): String => "gist-json-converter/absent-optional-fields" @@ -1891,32 +1966,32 @@ class \nodoc\ _TestGistJsonConverterAbsentOptionalFields let auth = lori.TCPConnectAuth(h.env.root) let creds = req.Credentials(auth) let b: String val = base.clone() - let obj = _TestGistJson(b) + let obj = _TestGistJSON(b) .remove("owner") .remove("user") .remove("comments_enabled") let json = JSONNav(obj) try let gist = - GistJsonConverter(json, creds)? - match gist.owner + GistJSONConverter(json, creds)? + match \exhaustive\ gist.owner | None => None | let _: User => h.fail("owner should be None") end - match gist.user + match \exhaustive\ gist.user | None => None | let _: User => h.fail("user should be None") end h.assert_true( gist.comments_enabled, - "comments_enabled should default " - + "to true") - h.assert_eq[String]("gid_" + b, - gist.id) - h.assert_eq[String]("gurl_" + b, - gist.url) + "comments_enabled should default " + + "to true") + h.assert_eq[String]( + "gid_" + b, gist.id) + h.assert_eq[String]( + "gurl_" + b, gist.url) else h.fail("converter raised an error") end @@ -1937,7 +2012,7 @@ class \nodoc\ _TestStringOrNoneReturnsString let obj = JSONObject.update("key", b) let json = JSONNav(obj) try - match JSONNavUtil.string_or_none( + match \exhaustive\ JSONNavUtil.string_or_none( json("key"))? | let s: String => h.assert_eq[String](b, s) @@ -1959,7 +2034,7 @@ class \nodoc\ _TestStringOrNoneReturnsNone fun ref apply(h: TestHelper) ? => let obj = JSONObject.update("key", None) let json = JSONNav(obj) - match JSONNavUtil.string_or_none( + match \exhaustive\ JSONNavUtil.string_or_none( json("key"))? | None => None | let _: String => @@ -1974,7 +2049,8 @@ class \nodoc\ _TestStringOrNoneRaisesOnInvalid fun ref apply(h: TestHelper) ? => PonyCheck.for_all[I64]( - recover val Generators.i64() end, h)( + recover val Generators.i64() end, + h)( {(value, h) => let obj = JSONObject.update("key", value) @@ -1983,8 +2059,8 @@ class \nodoc\ _TestStringOrNoneRaisesOnInvalid JSONNavUtil.string_or_none( json("key"))? h.fail( - "should raise for I64 value " - + value.string()) + "should raise for I64 value " + + value.string()) end })? // Missing key should also raise @@ -1996,51 +2072,62 @@ class \nodoc\ _TestStringOrNoneRaisesOnInvalid h.fail("should raise for missing key") end -class \nodoc\ _TestJsonTypeStringAllArms is UnitTest +class \nodoc\ _TestJSONTypeStringAllArms is UnitTest fun name(): String => "json-type-string/all-arms" fun ref apply(h: TestHelper) => let obj = JSONObject.update("a", "b") let arr = JSONArray.push("x") - let nav = JSONNav( - JSONObject - .update("obj", obj) - .update("arr", arr) - .update("str", "hello") - .update("i64", I64(42)) - .update("f64", F64(3.14)) - .update("bool", true) - .update("null", None)) - h.assert_eq[String](obj.print(), + let nav = + JSONNav( + JSONObject + .update("obj", obj) + .update("arr", arr) + .update("str", "hello") + .update("i64", I64(42)) + .update("f64", F64(3.14)) + .update("bool", true) + .update("null", None)) + h.assert_eq[String]( + obj.print(), req.JSONTypeString(nav("obj"))) - h.assert_eq[String](arr.print(), + h.assert_eq[String]( + arr.print(), req.JSONTypeString(nav("arr"))) - h.assert_eq[String]("hello", + h.assert_eq[String]( + "hello", req.JSONTypeString(nav("str"))) - h.assert_eq[String](I64(42).string(), + h.assert_eq[String]( + I64(42).string(), req.JSONTypeString(nav("i64"))) - h.assert_eq[String](F64(3.14).string(), + h.assert_eq[String]( + F64(3.14).string(), req.JSONTypeString(nav("f64"))) - h.assert_eq[String]("true", + h.assert_eq[String]( + "true", req.JSONTypeString(nav("bool"))) - h.assert_eq[String]("null", + h.assert_eq[String]( + "null", req.JSONTypeString(nav("null"))) - h.assert_eq[String]("JSONNotFound", + h.assert_eq[String]( + "JSONNotFound", req.JSONTypeString(nav("missing"))) -class \nodoc\ _TestJsonTypeStringI64Property +class \nodoc\ _TestJSONTypeStringI64Property is UnitTest fun name(): String => "json-type-string/i64-property" fun ref apply(h: TestHelper) ? => PonyCheck.for_all[I64]( - recover val Generators.i64() end, h)( + recover val Generators.i64() end, + h)( {(value, h) => let obj = JSONObject.update("k", value) let json = JSONNav(obj) - h.assert_eq[String](value.string(), + h.assert_eq[String]( + value.string(), req.JSONTypeString(json("k"))) })? diff --git a/github_rest_api/_test_mock_http_server.pony b/github_rest_api/_test_mock_http_server.pony index 22d7ffe..6d29616 100644 --- a/github_rest_api/_test_mock_http_server.pony +++ b/github_rest_api/_test_mock_http_server.pony @@ -22,13 +22,13 @@ primitive \nodoc\ _TestSSLContext let file_auth = FileAuth(h.env.root) recover val ssl.SSLContext - .>set_authority( + .> set_authority( FilePath(file_auth, "assets/cert.pem"))? - .>set_cert( + .> set_cert( FilePath(file_auth, "assets/cert.pem"), FilePath(file_auth, "assets/key.pem"))? - .>set_client_verify(false) - .>set_server_verify(false) + .> set_client_verify(false) + .> set_server_verify(false) end // Type aliases can't carry annotations; the underscore prefix keeps it @@ -57,11 +57,12 @@ actor \nodoc\ _MockHTTPListener is lori.TCPListenerActor _sslctx = sslctx _responder = responder _on_listening_cb = on_listening_cb - _tcp_listener = lori.TCPListener( - lori.TCPListenAuth(h.env.root), - _TestHost(), - port, - this) + _tcp_listener = + lori.TCPListener( + lori.TCPListenAuth(h.env.root), + _TestHost(), + port, + this) fun ref _listener(): lori.TCPListener => _tcp_listener @@ -93,12 +94,13 @@ actor \nodoc\ _MockHTTPConnection responder: _Responder) => _responder = responder - _tcp_connection = lori.TCPConnection.ssl_server( - server_auth, - sslctx, - fd, - this, - this) + _tcp_connection = + lori.TCPConnection.ssl_server( + server_auth, + sslctx, + fd, + this, + this) fun ref _connection(): lori.TCPConnection => _tcp_connection diff --git a/github_rest_api/_test_request_actors.pony b/github_rest_api/_test_request_actors.pony index a2af5c5..57af5e9 100644 --- a/github_rest_api/_test_request_actors.pony +++ b/github_rest_api/_test_request_actors.pony @@ -6,12 +6,13 @@ use ssl = "ssl/net" // --- Test receiver actors --- -actor \nodoc\ _TestJsonSuccessReceiver is req.JSONRequesterResultReceiver +actor \nodoc\ _TestJSONSuccessReceiver is req.JSONRequesterResultReceiver let _h: TestHelper let _expected_key: String let _expected_value: String - new create(h: TestHelper, + new create( + h: TestHelper, expected_key: String, expected_value: String) => @@ -29,19 +30,25 @@ actor \nodoc\ _TestJsonSuccessReceiver is req.JSONRequesterResultReceiver _h.complete(false) end - be failure(status: U16, response_body: String, message: String) => + be failure( + status: U16, + response_body: String, + message: String) + => _h.fail( - "Expected success, got failure: status=" + status.string() - + " body=" + response_body + " msg=" + message) + "Expected success, got failure: status=" + + status.string() + " body=" + response_body + + " msg=" + message) _h.complete(false) -actor \nodoc\ _TestJsonFailureReceiver is req.JSONRequesterResultReceiver +actor \nodoc\ _TestJSONFailureReceiver is req.JSONRequesterResultReceiver let _h: TestHelper let _expected_status: U16 let _expected_body: String let _expected_message: String - new create(h: TestHelper, + new create( + h: TestHelper, expected_status: U16, expected_body: String, expected_message: String) @@ -55,7 +62,11 @@ actor \nodoc\ _TestJsonFailureReceiver is req.JSONRequesterResultReceiver _h.fail("Expected failure, got success") _h.complete(false) - be failure(status: U16, response_body: String, message: String) => + be failure( + status: U16, + response_body: String, + message: String) + => _h.assert_eq[U16](_expected_status, status) _h.assert_eq[String](_expected_body, response_body) _h.assert_eq[String](_expected_message, message) @@ -70,10 +81,15 @@ actor \nodoc\ _TestDeleteSuccessReceiver is req.DeleteResultReceiver be success() => _h.complete(true) - be failure(status: U16, response_body: String, message: String) => + be failure( + status: U16, + response_body: String, + message: String) + => _h.fail( - "Expected success, got failure: status=" + status.string() - + " body=" + response_body + " msg=" + message) + "Expected success, got failure: status=" + + status.string() + " body=" + response_body + + " msg=" + message) _h.complete(false) actor \nodoc\ _TestDeleteFailureReceiver is req.DeleteResultReceiver @@ -81,7 +97,8 @@ actor \nodoc\ _TestDeleteFailureReceiver is req.DeleteResultReceiver let _expected_status: U16 let _expected_body: String - new create(h: TestHelper, + new create( + h: TestHelper, expected_status: U16, expected_body: String) => @@ -93,7 +110,11 @@ actor \nodoc\ _TestDeleteFailureReceiver is req.DeleteResultReceiver _h.fail("Expected failure, got success") _h.complete(false) - be failure(status: U16, response_body: String, message: String) => + be failure( + status: U16, + response_body: String, + message: String) + => _h.assert_eq[U16](_expected_status, status) _h.assert_eq[String](_expected_body, response_body) _h.complete(true) @@ -110,11 +131,15 @@ actor \nodoc\ _TestCheckSuccessReceiver is req.CheckResultReceiver _h.assert_eq[Bool](_expected, value) _h.complete(true) - be failure(status: U16, response_body: String, message: String) => + be failure( + status: U16, + response_body: String, + message: String) + => _h.fail( - "Expected success(" + _expected.string() - + "), got failure: status=" + status.string() - + " body=" + response_body + " msg=" + message) + "Expected success(" + _expected.string() + + "), got failure: status=" + status.string() + + " body=" + response_body + " msg=" + message) _h.complete(false) actor \nodoc\ _TestCheckFailureReceiver is req.CheckResultReceiver @@ -122,7 +147,8 @@ actor \nodoc\ _TestCheckFailureReceiver is req.CheckResultReceiver let _expected_status: U16 let _expected_body: String - new create(h: TestHelper, + new create( + h: TestHelper, expected_status: U16, expected_body: String) => @@ -131,10 +157,16 @@ actor \nodoc\ _TestCheckFailureReceiver is req.CheckResultReceiver _expected_body = expected_body be success(value: Bool) => - _h.fail("Expected failure, got success(" + value.string() + ")") + _h.fail( + "Expected failure, got success(" + + value.string() + ")") _h.complete(false) - be failure(status: U16, response_body: String, message: String) => + be failure( + status: U16, + response_body: String, + message: String) + => _h.assert_eq[U16](_expected_status, status) _h.assert_eq[String](_expected_body, response_body) _h.complete(true) @@ -145,7 +177,8 @@ actor \nodoc\ _TestLinkedSuccessReceiver is LinkedResultReceiver let _expected_value: String let _expected_link: String - new create(h: TestHelper, + new create( + h: TestHelper, expected_key: String, expected_value: String, expected_link: String) @@ -166,10 +199,15 @@ actor \nodoc\ _TestLinkedSuccessReceiver is LinkedResultReceiver _h.complete(false) end - be failure(status: U16, response_body: String, message: String) => + be failure( + status: U16, + response_body: String, + message: String) + => _h.fail( - "Expected success, got failure: status=" + status.string() - + " body=" + response_body + " msg=" + message) + "Expected success, got failure: status=" + + status.string() + " body=" + response_body + + " msg=" + message) _h.complete(false) actor \nodoc\ _TestLinkedFailureReceiver is LinkedResultReceiver @@ -177,7 +215,8 @@ actor \nodoc\ _TestLinkedFailureReceiver is LinkedResultReceiver let _expected_status: U16 let _expected_body: String - new create(h: TestHelper, + new create( + h: TestHelper, expected_status: U16, expected_body: String) => @@ -189,14 +228,17 @@ actor \nodoc\ _TestLinkedFailureReceiver is LinkedResultReceiver _h.fail("Expected failure, got success") _h.complete(false) - be failure(status: U16, response_body: String, message: String) => + be failure( + status: U16, + response_body: String, + message: String) + => _h.assert_eq[U16](_expected_status, status) _h.assert_eq[String](_expected_body, response_body) _h.complete(true) // --- Test classes --- - -class \nodoc\ _TestJsonRequesterGetSuccess is UnitTest +class \nodoc\ _TestJSONRequesterGetSuccess is UnitTest fun name(): String => "request-actors/json-requester/get-success" fun ref apply(h: TestHelper) ? => @@ -204,111 +246,154 @@ class \nodoc\ _TestJsonRequesterGetSuccess is UnitTest let sslctx = _TestSSLContext(h)? let host = _TestHost() let port: String = "48100" - let url = _TestUrl(host, port, "/test") - let creds = req.Credentials( - lori.TCPConnectAuth(h.env.root) where ssl_ctx' = sslctx) - let receiver = _TestJsonSuccessReceiver(h, "greeting", "hello") + let url = _TestURL(host, port, "/test") + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root) + where ssl_ctx' = sslctx) + let receiver = + _TestJSONSuccessReceiver(h, "greeting", "hello") let responder: _Responder = {(request: String): String => let body = """{"greeting":"hello"}""" - "HTTP/1.1 200 OK\r\n" - + "Content-Length: " + body.size().string() + "\r\n" - + "\r\n" - + body + "HTTP/1.1 200 OK\r\n" + + "Content-Length: " + body.size().string() + + "\r\n" + + "\r\n" + + body } val - let listener = _MockHTTPListener(h, port, sslctx, responder, - {()(creds, url, receiver) => - req.JSONRequester.get(creds, url, receiver) - } val) + let listener = + _MockHTTPListener( + h, + port, + sslctx, + responder, + {()(creds, url, receiver) => + req.JSONRequester.get(creds, url, receiver) + } val) h.dispose_when_done(listener) -class \nodoc\ _TestJsonRequesterGetFailure is UnitTest - fun name(): String => "request-actors/json-requester/get-failure" +class \nodoc\ _TestJSONRequesterGetFailure is UnitTest + fun name(): String => + "request-actors/json-requester/get-failure" fun ref apply(h: TestHelper) ? => h.long_test(5_000_000_000) let sslctx = _TestSSLContext(h)? let host = _TestHost() let port: String = "48101" - let url = _TestUrl(host, port, "/missing") - let creds = req.Credentials( - lori.TCPConnectAuth(h.env.root) where ssl_ctx' = sslctx) - let receiver = _TestJsonFailureReceiver(h, 404, "not found here", "") + let url = _TestURL(host, port, "/missing") + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root) + where ssl_ctx' = sslctx) + let receiver = + _TestJSONFailureReceiver( + h, 404, "not found here", "") let responder: _Responder = {(request: String): String => let body = "not found here" - "HTTP/1.1 404 Not Found\r\n" - + "Content-Length: " + body.size().string() + "\r\n" - + "\r\n" - + body + "HTTP/1.1 404 Not Found\r\n" + + "Content-Length: " + body.size().string() + + "\r\n" + + "\r\n" + + body } val - let listener = _MockHTTPListener(h, port, sslctx, responder, - {()(creds, url, receiver) => - req.JSONRequester.get(creds, url, receiver) - } val) + let listener = + _MockHTTPListener( + h, + port, + sslctx, + responder, + {()(creds, url, receiver) => + req.JSONRequester.get(creds, url, receiver) + } val) h.dispose_when_done(listener) -class \nodoc\ _TestJsonRequesterPostSuccess is UnitTest - fun name(): String => "request-actors/json-requester/post-success" +class \nodoc\ _TestJSONRequesterPostSuccess is UnitTest + fun name(): String => + "request-actors/json-requester/post-success" fun ref apply(h: TestHelper) ? => h.long_test(5_000_000_000) let sslctx = _TestSSLContext(h)? let host = _TestHost() let port: String = "48102" - let url = _TestUrl(host, port, "/create") - let creds = req.Credentials( - lori.TCPConnectAuth(h.env.root) where ssl_ctx' = sslctx) - let receiver = _TestJsonSuccessReceiver(h, "id", "42") + let url = _TestURL(host, port, "/create") + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root) + where ssl_ctx' = sslctx) + let receiver = + _TestJSONSuccessReceiver(h, "id", "42") let responder: _Responder = {(request: String): String => let body = """{"id":"42"}""" - "HTTP/1.1 201 Created\r\n" - + "Content-Length: " + body.size().string() + "\r\n" - + "\r\n" - + body + "HTTP/1.1 201 Created\r\n" + + "Content-Length: " + body.size().string() + + "\r\n" + + "\r\n" + + body } val - let listener = _MockHTTPListener(h, port, sslctx, responder, - {()(creds, url, receiver) => - req.JSONRequester.post(creds, url, "{}", receiver) - } val) + let listener = + _MockHTTPListener( + h, + port, + sslctx, + responder, + {()(creds, url, receiver) => + req.JSONRequester.post( + creds, url, "{}", receiver) + } val) h.dispose_when_done(listener) -class \nodoc\ _TestJsonRequesterGetRedirect is UnitTest - fun name(): String => "request-actors/json-requester/get-redirect" +class \nodoc\ _TestJSONRequesterGetRedirect is UnitTest + fun name(): String => + "request-actors/json-requester/get-redirect" fun ref apply(h: TestHelper) ? => h.long_test(5_000_000_000) let sslctx = _TestSSLContext(h)? let host = _TestHost() let port: String = "48103" - let url = _TestUrl(host, port, "/original") - let redirect_target = _TestUrl(host, port, "/redirected") - let creds = req.Credentials( - lori.TCPConnectAuth(h.env.root) where ssl_ctx' = sslctx) - let receiver = _TestJsonSuccessReceiver(h, "status", "redirected") + let url = _TestURL(host, port, "/original") + let redirect_target = + _TestURL(host, port, "/redirected") + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root) + where ssl_ctx' = sslctx) + let receiver = + _TestJSONSuccessReceiver( + h, "status", "redirected") let responder: _Responder = {(request: String)(redirect_target): String => if request.contains("GET /redirected") then let body = """{"status":"redirected"}""" - "HTTP/1.1 200 OK\r\n" - + "Content-Length: " + body.size().string() + "\r\n" - + "\r\n" - + body + "HTTP/1.1 200 OK\r\n" + + "Content-Length: " + + body.size().string() + "\r\n" + + "\r\n" + + body else - "HTTP/1.1 301 Moved Permanently\r\n" - + "Location: " + redirect_target + "\r\n" - + "Content-Length: 0\r\n" - + "\r\n" + "HTTP/1.1 301 Moved Permanently\r\n" + + "Location: " + redirect_target + "\r\n" + + "Content-Length: 0\r\n" + + "\r\n" end } val - let listener = _MockHTTPListener(h, port, sslctx, responder, - {()(creds, url, receiver) => - req.JSONRequester.get(creds, url, receiver) - } val) + let listener = + _MockHTTPListener( + h, + port, + sslctx, + responder, + {()(creds, url, receiver) => + req.JSONRequester.get(creds, url, receiver) + } val) h.dispose_when_done(listener) -class \nodoc\ _TestJsonRequesterGetParseError is UnitTest +class \nodoc\ _TestJSONRequesterGetParseError is UnitTest fun name(): String => "request-actors/json-requester/get-parse-error" @@ -317,23 +402,32 @@ class \nodoc\ _TestJsonRequesterGetParseError is UnitTest let sslctx = _TestSSLContext(h)? let host = _TestHost() let port: String = "48104" - let url = _TestUrl(host, port, "/bad-json") - let creds = req.Credentials( - lori.TCPConnectAuth(h.env.root) where ssl_ctx' = sslctx) - let receiver = _TestJsonFailureReceiver( - h, 200, "", "Failed to parse response") + let url = _TestURL(host, port, "/bad-json") + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root) + where ssl_ctx' = sslctx) + let receiver = + _TestJSONFailureReceiver( + h, 200, "", "Failed to parse response") let responder: _Responder = {(request: String): String => let body = "this is not json{{" - "HTTP/1.1 200 OK\r\n" - + "Content-Length: " + body.size().string() + "\r\n" - + "\r\n" - + body + "HTTP/1.1 200 OK\r\n" + + "Content-Length: " + body.size().string() + + "\r\n" + + "\r\n" + + body } val - let listener = _MockHTTPListener(h, port, sslctx, responder, - {()(creds, url, receiver) => - req.JSONRequester.get(creds, url, receiver) - } val) + let listener = + _MockHTTPListener( + h, + port, + sslctx, + responder, + {()(creds, url, receiver) => + req.JSONRequester.get(creds, url, receiver) + } val) h.dispose_when_done(listener) class \nodoc\ _TestNoContentDeleteSuccess is UnitTest @@ -345,20 +439,28 @@ class \nodoc\ _TestNoContentDeleteSuccess is UnitTest let sslctx = _TestSSLContext(h)? let host = _TestHost() let port: String = "48105" - let url = _TestUrl(host, port, "/delete-me") - let creds = req.Credentials( - lori.TCPConnectAuth(h.env.root) where ssl_ctx' = sslctx) + let url = _TestURL(host, port, "/delete-me") + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root) + where ssl_ctx' = sslctx) let receiver = _TestDeleteSuccessReceiver(h) let responder: _Responder = {(request: String): String => - "HTTP/1.1 204 No Content\r\n" - + "Content-Length: 0\r\n" - + "\r\n" + "HTTP/1.1 204 No Content\r\n" + + "Content-Length: 0\r\n" + + "\r\n" } val - let listener = _MockHTTPListener(h, port, sslctx, responder, - {()(creds, url, receiver) => - req.NoContentRequester.delete(creds, url, receiver) - } val) + let listener = + _MockHTTPListener( + h, + port, + sslctx, + responder, + {()(creds, url, receiver) => + req.NoContentRequester.delete( + creds, url, receiver) + } val) h.dispose_when_done(listener) class \nodoc\ _TestNoContentDeleteFailure is UnitTest @@ -370,96 +472,134 @@ class \nodoc\ _TestNoContentDeleteFailure is UnitTest let sslctx = _TestSSLContext(h)? let host = _TestHost() let port: String = "48106" - let url = _TestUrl(host, port, "/no-access") - let creds = req.Credentials( - lori.TCPConnectAuth(h.env.root) where ssl_ctx' = sslctx) - let receiver = _TestDeleteFailureReceiver(h, 403, "forbidden") + let url = _TestURL(host, port, "/no-access") + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root) + where ssl_ctx' = sslctx) + let receiver = + _TestDeleteFailureReceiver(h, 403, "forbidden") let responder: _Responder = {(request: String): String => let body = "forbidden" - "HTTP/1.1 403 Forbidden\r\n" - + "Content-Length: " + body.size().string() + "\r\n" - + "\r\n" - + body + "HTTP/1.1 403 Forbidden\r\n" + + "Content-Length: " + body.size().string() + + "\r\n" + + "\r\n" + + body } val - let listener = _MockHTTPListener(h, port, sslctx, responder, - {()(creds, url, receiver) => - req.NoContentRequester.delete(creds, url, receiver) - } val) + let listener = + _MockHTTPListener( + h, + port, + sslctx, + responder, + {()(creds, url, receiver) => + req.NoContentRequester.delete( + creds, url, receiver) + } val) h.dispose_when_done(listener) class \nodoc\ _TestCheckRequester204 is UnitTest - fun name(): String => "request-actors/check-requester/204-true" + fun name(): String => + "request-actors/check-requester/204-true" fun ref apply(h: TestHelper) ? => h.long_test(5_000_000_000) let sslctx = _TestSSLContext(h)? let host = _TestHost() let port: String = "48107" - let url = _TestUrl(host, port, "/starred") - let creds = req.Credentials( - lori.TCPConnectAuth(h.env.root) where ssl_ctx' = sslctx) - let receiver = _TestCheckSuccessReceiver(h, true) + let url = _TestURL(host, port, "/starred") + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root) + where ssl_ctx' = sslctx) + let receiver = + _TestCheckSuccessReceiver(h, true) let responder: _Responder = {(request: String): String => - "HTTP/1.1 204 No Content\r\n" - + "Content-Length: 0\r\n" - + "\r\n" + "HTTP/1.1 204 No Content\r\n" + + "Content-Length: 0\r\n" + + "\r\n" } val - let listener = _MockHTTPListener(h, port, sslctx, responder, - {()(creds, url, receiver) => - req.CheckRequester(creds, url, receiver) - } val) + let listener = + _MockHTTPListener( + h, + port, + sslctx, + responder, + {()(creds, url, receiver) => + req.CheckRequester(creds, url, receiver) + } val) h.dispose_when_done(listener) class \nodoc\ _TestCheckRequester404 is UnitTest - fun name(): String => "request-actors/check-requester/404-false" + fun name(): String => + "request-actors/check-requester/404-false" fun ref apply(h: TestHelper) ? => h.long_test(5_000_000_000) let sslctx = _TestSSLContext(h)? let host = _TestHost() let port: String = "48108" - let url = _TestUrl(host, port, "/not-starred") - let creds = req.Credentials( - lori.TCPConnectAuth(h.env.root) where ssl_ctx' = sslctx) - let receiver = _TestCheckSuccessReceiver(h, false) + let url = _TestURL(host, port, "/not-starred") + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root) + where ssl_ctx' = sslctx) + let receiver = + _TestCheckSuccessReceiver(h, false) let responder: _Responder = {(request: String): String => - "HTTP/1.1 404 Not Found\r\n" - + "Content-Length: 0\r\n" - + "\r\n" + "HTTP/1.1 404 Not Found\r\n" + + "Content-Length: 0\r\n" + + "\r\n" } val - let listener = _MockHTTPListener(h, port, sslctx, responder, - {()(creds, url, receiver) => - req.CheckRequester(creds, url, receiver) - } val) + let listener = + _MockHTTPListener( + h, + port, + sslctx, + responder, + {()(creds, url, receiver) => + req.CheckRequester(creds, url, receiver) + } val) h.dispose_when_done(listener) class \nodoc\ _TestCheckRequesterOther is UnitTest - fun name(): String => "request-actors/check-requester/other-failure" + fun name(): String => + "request-actors/check-requester/other-failure" fun ref apply(h: TestHelper) ? => h.long_test(5_000_000_000) let sslctx = _TestSSLContext(h)? let host = _TestHost() let port: String = "48109" - let url = _TestUrl(host, port, "/broken") - let creds = req.Credentials( - lori.TCPConnectAuth(h.env.root) where ssl_ctx' = sslctx) - let receiver = _TestCheckFailureReceiver(h, 500, "server error") + let url = _TestURL(host, port, "/broken") + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root) + where ssl_ctx' = sslctx) + let receiver = + _TestCheckFailureReceiver(h, 500, "server error") let responder: _Responder = {(request: String): String => let body = "server error" - "HTTP/1.1 500 Internal Server Error\r\n" - + "Content-Length: " + body.size().string() + "\r\n" - + "\r\n" - + body + "HTTP/1.1 500 Internal Server Error\r\n" + + "Content-Length: " + body.size().string() + + "\r\n" + + "\r\n" + + body } val - let listener = _MockHTTPListener(h, port, sslctx, responder, - {()(creds, url, receiver) => - req.CheckRequester(creds, url, receiver) - } val) + let listener = + _MockHTTPListener( + h, + port, + sslctx, + responder, + {()(creds, url, receiver) => + req.CheckRequester(creds, url, receiver) + } val) h.dispose_when_done(listener) class \nodoc\ _TestLinkedWithLink is UnitTest @@ -471,26 +611,36 @@ class \nodoc\ _TestLinkedWithLink is UnitTest let sslctx = _TestSSLContext(h)? let host = _TestHost() let port: String = "48110" - let url = _TestUrl(host, port, "/list") - let creds = req.Credentials( - lori.TCPConnectAuth(h.env.root) where ssl_ctx' = sslctx) + let url = _TestURL(host, port, "/list") + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root) + where ssl_ctx' = sslctx) let link_value = - "; rel=\"next\"" - let receiver = _TestLinkedSuccessReceiver( - h, "item", "one", link_value) + "" + + "; rel=\"next\"" + let receiver = + _TestLinkedSuccessReceiver( + h, "item", "one", link_value) let responder: _Responder = {(request: String)(link_value): String => let body = """{"item":"one"}""" - "HTTP/1.1 200 OK\r\n" - + "Content-Length: " + body.size().string() + "\r\n" - + "Link: " + link_value + "\r\n" - + "\r\n" - + body + "HTTP/1.1 200 OK\r\n" + + "Content-Length: " + body.size().string() + + "\r\n" + + "Link: " + link_value + "\r\n" + + "\r\n" + + body } val - let listener = _MockHTTPListener(h, port, sslctx, responder, - {()(creds, url, receiver) => - LinkedJsonRequester(creds, url, receiver) - } val) + let listener = + _MockHTTPListener( + h, + port, + sslctx, + responder, + {()(creds, url, receiver) => + LinkedJSONRequester(creds, url, receiver) + } val) h.dispose_when_done(listener) class \nodoc\ _TestLinkedNoLink is UnitTest @@ -502,22 +652,32 @@ class \nodoc\ _TestLinkedNoLink is UnitTest let sslctx = _TestSSLContext(h)? let host = _TestHost() let port: String = "48111" - let url = _TestUrl(host, port, "/list") - let creds = req.Credentials( - lori.TCPConnectAuth(h.env.root) where ssl_ctx' = sslctx) - let receiver = _TestLinkedSuccessReceiver(h, "item", "two", "") + let url = _TestURL(host, port, "/list") + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root) + where ssl_ctx' = sslctx) + let receiver = + _TestLinkedSuccessReceiver( + h, "item", "two", "") let responder: _Responder = {(request: String): String => let body = """{"item":"two"}""" - "HTTP/1.1 200 OK\r\n" - + "Content-Length: " + body.size().string() + "\r\n" - + "\r\n" - + body + "HTTP/1.1 200 OK\r\n" + + "Content-Length: " + body.size().string() + + "\r\n" + + "\r\n" + + body } val - let listener = _MockHTTPListener(h, port, sslctx, responder, - {()(creds, url, receiver) => - LinkedJsonRequester(creds, url, receiver) - } val) + let listener = + _MockHTTPListener( + h, + port, + sslctx, + responder, + {()(creds, url, receiver) => + LinkedJSONRequester(creds, url, receiver) + } val) h.dispose_when_done(listener) class \nodoc\ _TestLinkedFailure is UnitTest @@ -529,67 +689,94 @@ class \nodoc\ _TestLinkedFailure is UnitTest let sslctx = _TestSSLContext(h)? let host = _TestHost() let port: String = "48112" - let url = _TestUrl(host, port, "/broken") - let creds = req.Credentials( - lori.TCPConnectAuth(h.env.root) where ssl_ctx' = sslctx) - let receiver = _TestLinkedFailureReceiver(h, 500, "internal error") + let url = _TestURL(host, port, "/broken") + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root) + where ssl_ctx' = sslctx) + let receiver = + _TestLinkedFailureReceiver( + h, 500, "internal error") let responder: _Responder = {(request: String): String => let body = "internal error" - "HTTP/1.1 500 Internal Server Error\r\n" - + "Content-Length: " + body.size().string() + "\r\n" - + "\r\n" - + body + "HTTP/1.1 500 Internal Server Error\r\n" + + "Content-Length: " + body.size().string() + + "\r\n" + + "\r\n" + + body } val - let listener = _MockHTTPListener(h, port, sslctx, responder, - {()(creds, url, receiver) => - LinkedJsonRequester(creds, url, receiver) - } val) + let listener = + _MockHTTPListener( + h, + port, + sslctx, + responder, + {()(creds, url, receiver) => + LinkedJSONRequester(creds, url, receiver) + } val) h.dispose_when_done(listener) class \nodoc\ _TestBearerTokenSent is UnitTest - fun name(): String => "request-actors/bearer-token-sent" + fun name(): String => + "request-actors/bearer-token-sent" fun ref apply(h: TestHelper) ? => h.long_test(5_000_000_000) let sslctx = _TestSSLContext(h)? let host = _TestHost() let port: String = "48113" - let url = _TestUrl(host, port, "/auth-check") - let creds = req.Credentials( - lori.TCPConnectAuth(h.env.root) - where token' = "ghp_test_token_12345", ssl_ctx' = sslctx) - let receiver = _TestJsonSuccessReceiver(h, "result", "ok") + let url = _TestURL(host, port, "/auth-check") + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root) + where + token' = "ghp_test_token_12345", + ssl_ctx' = sslctx) + let receiver = + _TestJSONSuccessReceiver(h, "result", "ok") let responder: _Responder = {(request: String): String => let body = - if request.contains("authorization: Bearer ghp_test_token_12345") + if request.contains( + "authorization: Bearer " + + "ghp_test_token_12345") then """{"result":"ok"}""" else """{"result":"missing-auth"}""" end - "HTTP/1.1 200 OK\r\n" - + "Content-Length: " + body.size().string() + "\r\n" - + "\r\n" - + body + "HTTP/1.1 200 OK\r\n" + + "Content-Length: " + body.size().string() + + "\r\n" + + "\r\n" + + body } val - let listener = _MockHTTPListener(h, port, sslctx, responder, - {()(creds, url, receiver) => - req.JSONRequester.get(creds, url, receiver) - } val) + let listener = + _MockHTTPListener( + h, + port, + sslctx, + responder, + {()(creds, url, receiver) => + req.JSONRequester.get(creds, url, receiver) + } val) h.dispose_when_done(listener) class \nodoc\ _TestNoTokenNoAuthHeader is UnitTest - fun name(): String => "request-actors/no-token-no-auth-header" + fun name(): String => + "request-actors/no-token-no-auth-header" fun ref apply(h: TestHelper) ? => h.long_test(5_000_000_000) let sslctx = _TestSSLContext(h)? let host = _TestHost() let port: String = "48114" - let url = _TestUrl(host, port, "/no-auth-check") - let creds = req.Credentials( - lori.TCPConnectAuth(h.env.root) where ssl_ctx' = sslctx) - let receiver = _TestJsonSuccessReceiver(h, "result", "ok") + let url = _TestURL(host, port, "/no-auth-check") + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root) + where ssl_ctx' = sslctx) + let receiver = + _TestJSONSuccessReceiver(h, "result", "ok") let responder: _Responder = {(request: String): String => let body = @@ -597,21 +784,31 @@ class \nodoc\ _TestNoTokenNoAuthHeader is UnitTest then """{"result":"unexpected-auth"}""" else """{"result":"ok"}""" end - "HTTP/1.1 200 OK\r\n" - + "Content-Length: " + body.size().string() + "\r\n" - + "\r\n" - + body + "HTTP/1.1 200 OK\r\n" + + "Content-Length: " + body.size().string() + + "\r\n" + + "\r\n" + + body } val - let listener = _MockHTTPListener(h, port, sslctx, responder, - {()(creds, url, receiver) => - req.JSONRequester.get(creds, url, receiver) - } val) + let listener = + _MockHTTPListener( + h, + port, + sslctx, + responder, + {()(creds, url, receiver) => + req.JSONRequester.get(creds, url, receiver) + } val) h.dispose_when_done(listener) // --- URL helper --- - -primitive \nodoc\ _TestUrl - fun apply(host: String, port: String, path: String): String val => +primitive \nodoc\ _TestURL + fun apply( + host: String, + port: String, + path: String) + : String val + => recover val "https://" + host + ":" + port + path end diff --git a/github_rest_api/_test_result_receivers.pony b/github_rest_api/_test_result_receivers.pony index 4432def..37c582f 100644 --- a/github_rest_api/_test_result_receivers.pony +++ b/github_rest_api/_test_result_receivers.pony @@ -16,11 +16,13 @@ class \nodoc\ _TestDeletedResultReceiverSuccess is UnitTest let p = Promise[req.DeletedOrError] p.next[None]( {(result: req.DeletedOrError)(h) => - match result + match \exhaustive\ result | let _: req.Deleted => h.complete(true) | let e: req.RequestError => - h.fail("Expected Deleted, got RequestError: " + e.message) + h.fail( + "Expected Deleted, got RequestError: " + + e.message) h.complete(false) end }) @@ -35,13 +37,15 @@ class \nodoc\ _TestDeletedResultReceiverFailure is UnitTest let p = Promise[req.DeletedOrError] p.next[None]( {(result: req.DeletedOrError)(h) => - match result + match \exhaustive\ result | let _: req.Deleted => - h.fail("Expected RequestError, got Deleted") + h.fail( + "Expected RequestError, got Deleted") h.complete(false) | let e: req.RequestError => h.assert_eq[U16](404, e.status) - h.assert_eq[String]("not found", e.response_body) + h.assert_eq[String]( + "not found", e.response_body) h.assert_eq[String]("msg", e.message) h.complete(true) end @@ -50,19 +54,22 @@ class \nodoc\ _TestDeletedResultReceiverFailure is UnitTest receiver.failure(404, "not found", "msg") class \nodoc\ _TestBoolResultReceiverSuccessTrue is UnitTest - fun name(): String => "result-receivers/bool/success-true" + fun name(): String => + "result-receivers/bool/success-true" fun ref apply(h: TestHelper) => h.long_test(2_000_000_000) let p = Promise[req.BoolOrError] p.next[None]( {(result: req.BoolOrError)(h) => - match result + match \exhaustive\ result | let b: Bool => h.assert_true(b, "Expected true") h.complete(true) | let e: req.RequestError => - h.fail("Expected Bool, got RequestError: " + e.message) + h.fail( + "Expected Bool, got RequestError: " + + e.message) h.complete(false) end }) @@ -70,19 +77,22 @@ class \nodoc\ _TestBoolResultReceiverSuccessTrue is UnitTest receiver.success(true) class \nodoc\ _TestBoolResultReceiverSuccessFalse is UnitTest - fun name(): String => "result-receivers/bool/success-false" + fun name(): String => + "result-receivers/bool/success-false" fun ref apply(h: TestHelper) => h.long_test(2_000_000_000) let p = Promise[req.BoolOrError] p.next[None]( {(result: req.BoolOrError)(h) => - match result + match \exhaustive\ result | let b: Bool => h.assert_false(b, "Expected false") h.complete(true) | let e: req.RequestError => - h.fail("Expected Bool, got RequestError: " + e.message) + h.fail( + "Expected Bool, got RequestError: " + + e.message) h.complete(false) end }) @@ -90,129 +100,165 @@ class \nodoc\ _TestBoolResultReceiverSuccessFalse is UnitTest receiver.success(false) class \nodoc\ _TestBoolResultReceiverFailure is UnitTest - fun name(): String => "result-receivers/bool/failure" + fun name(): String => + "result-receivers/bool/failure" fun ref apply(h: TestHelper) => h.long_test(2_000_000_000) let p = Promise[req.BoolOrError] p.next[None]( {(result: req.BoolOrError)(h) => - match result + match \exhaustive\ result | let _: Bool => - h.fail("Expected RequestError, got Bool") + h.fail( + "Expected RequestError, got Bool") h.complete(false) | let e: req.RequestError => h.assert_eq[U16](422, e.status) - h.assert_eq[String]("unprocessable", e.response_body) - h.assert_eq[String]("validation failed", e.message) + h.assert_eq[String]( + "unprocessable", e.response_body) + h.assert_eq[String]( + "validation failed", e.message) h.complete(true) end }) let receiver = req.BoolResultReceiver(p) - receiver.failure(422, "unprocessable", "validation failed") + receiver.failure( + 422, "unprocessable", "validation failed") class \nodoc\ _TestResultReceiverSuccess is UnitTest - fun name(): String => "result-receivers/json/success" + fun name(): String => + "result-receivers/json/success" fun ref apply(h: TestHelper) => h.long_test(2_000_000_000) let p = Promise[(String | req.RequestError)] p.next[None]( {(result: (String | req.RequestError))(h) => - match result + match \exhaustive\ result | let s: String => h.assert_eq[String]("hello", s) h.complete(true) | let e: req.RequestError => h.fail( - "Expected String, got RequestError: " + e.message) + "Expected String, got RequestError: " + + e.message) h.complete(false) end }) - let creds = req.Credentials(lori.TCPConnectAuth(h.env.root)) - let receiver = req.ResultReceiver[String]( - creds, p, _TestStringConverter) + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root)) + let receiver = + req.ResultReceiver[String]( + creds, p, _TestStringConverter) let obj = JSONObject.update("value", "hello") receiver.success(JSONNav(obj)) class \nodoc\ _TestResultReceiverConverterError is UnitTest - fun name(): String => "result-receivers/json/converter-error" + fun name(): String => + "result-receivers/json/converter-error" fun ref apply(h: TestHelper) => h.long_test(2_000_000_000) let p = Promise[(String | req.RequestError)] p.next[None]( {(result: (String | req.RequestError))(h) => - match result + match \exhaustive\ result | let _: String => - h.fail("Expected RequestError, got String") + h.fail( + "Expected RequestError, got String") h.complete(false) | let e: req.RequestError => h.assert_true( - e.message.contains("Unable to convert json"), - "Expected 'Unable to convert json', got: " - + e.message) + e.message.contains( + "Unable to convert json"), + "Expected 'Unable to convert json'" + + ", got: " + e.message) h.complete(true) end }) - let creds = req.Credentials(lori.TCPConnectAuth(h.env.root)) - let receiver = req.ResultReceiver[String]( - creds, p, _TestStringConverter) + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root)) + let receiver = + req.ResultReceiver[String]( + creds, p, _TestStringConverter) receiver.success(JSONNav(JSONObject)) class \nodoc\ _TestResultReceiverFailure is UnitTest - fun name(): String => "result-receivers/json/failure" + fun name(): String => + "result-receivers/json/failure" fun ref apply(h: TestHelper) => h.long_test(2_000_000_000) let p = Promise[(String | req.RequestError)] p.next[None]( {(result: (String | req.RequestError))(h) => - match result + match \exhaustive\ result | let _: String => - h.fail("Expected RequestError, got String") + h.fail( + "Expected RequestError, got String") h.complete(false) | let e: req.RequestError => h.assert_eq[U16](500, e.status) - h.assert_eq[String]("server error", e.response_body) - h.assert_eq[String]("internal", e.message) + h.assert_eq[String]( + "server error", e.response_body) + h.assert_eq[String]( + "internal", e.message) h.complete(true) end }) - let creds = req.Credentials(lori.TCPConnectAuth(h.env.root)) - let receiver = req.ResultReceiver[String]( - creds, p, _TestStringConverter) - receiver.failure(500, "server error", "internal") + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root)) + let receiver = + req.ResultReceiver[String]( + creds, p, _TestStringConverter) + receiver.failure( + 500, "server error", "internal") class \nodoc\ _TestPaginatedResultReceiverSuccess is UnitTest - fun name(): String => "result-receivers/paginated/success" + fun name(): String => + "result-receivers/paginated/success" fun ref apply(h: TestHelper) => h.long_test(2_000_000_000) - let p = Promise[(PaginatedList[String] | req.RequestError)] + let p = + Promise[ + (PaginatedList[String] | req.RequestError)] p.next[None]( - {(result: (PaginatedList[String] | req.RequestError))(h) => - match result + {(result: + (PaginatedList[String] | req.RequestError)) + (h) + => + match \exhaustive\ result | let pl: PaginatedList[String] => - h.assert_eq[USize](1, pl.results.size()) + h.assert_eq[USize]( + 1, pl.results.size()) try - h.assert_eq[String]("item1", pl.results(0)?) + h.assert_eq[String]( + "item1", pl.results(0)?) else h.fail("Failed to access results(0)") end h.complete(true) | let e: req.RequestError => h.fail( - "Expected PaginatedList, got RequestError: " - + e.message) + "Expected PaginatedList, " + + "got RequestError: " + e.message) h.complete(false) end }) - let creds = req.Credentials(lori.TCPConnectAuth(h.env.root)) - let converter = PaginatedListJsonConverter[String]( - creds, _TestStringConverter) - let receiver = PaginatedResultReceiver[String]( - creds, p, converter) + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root)) + let converter = + PaginatedListJSONConverter[String]( + creds, _TestStringConverter) + let receiver = + PaginatedResultReceiver[String]( + creds, p, converter) let arr = JSONArray .push(JSONObject.update("value", "item1")) receiver.success(JSONNav(arr), "") @@ -223,85 +269,123 @@ class \nodoc\ _TestPaginatedResultReceiverConverterError is UnitTest fun ref apply(h: TestHelper) => h.long_test(2_000_000_000) - let p = Promise[(PaginatedList[String] | req.RequestError)] + let p = + Promise[ + (PaginatedList[String] | req.RequestError)] p.next[None]( - {(result: (PaginatedList[String] | req.RequestError))(h) => - match result + {(result: + (PaginatedList[String] | req.RequestError)) + (h) + => + match \exhaustive\ result | let _: PaginatedList[String] => - h.fail("Expected RequestError, got PaginatedList") + h.fail( + "Expected RequestError, " + + "got PaginatedList") h.complete(false) | let e: req.RequestError => h.assert_true( - e.message.contains("Unable to convert json"), - "Expected 'Unable to convert json', got: " - + e.message) + e.message.contains( + "Unable to convert json"), + "Expected 'Unable to convert json'" + + ", got: " + e.message) h.complete(true) end }) - let creds = req.Credentials(lori.TCPConnectAuth(h.env.root)) - let converter = PaginatedListJsonConverter[String]( - creds, _TestStringConverter) - let receiver = PaginatedResultReceiver[String]( - creds, p, converter) + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root)) + let converter = + PaginatedListJSONConverter[String]( + creds, _TestStringConverter) + let receiver = + PaginatedResultReceiver[String]( + creds, p, converter) receiver.success(JSONNav("not-an-array"), "") class \nodoc\ _TestPaginatedResultReceiverFailure is UnitTest - fun name(): String => "result-receivers/paginated/failure" + fun name(): String => + "result-receivers/paginated/failure" fun ref apply(h: TestHelper) => h.long_test(2_000_000_000) - let p = Promise[(PaginatedList[String] | req.RequestError)] + let p = + Promise[ + (PaginatedList[String] | req.RequestError)] p.next[None]( - {(result: (PaginatedList[String] | req.RequestError))(h) => - match result + {(result: + (PaginatedList[String] | req.RequestError)) + (h) + => + match \exhaustive\ result | let _: PaginatedList[String] => - h.fail("Expected RequestError, got PaginatedList") + h.fail( + "Expected RequestError, " + + "got PaginatedList") h.complete(false) | let e: req.RequestError => h.assert_eq[U16](403, e.status) - h.assert_eq[String]("forbidden", e.response_body) - h.assert_eq[String]("auth failed", e.message) + h.assert_eq[String]( + "forbidden", e.response_body) + h.assert_eq[String]( + "auth failed", e.message) h.complete(true) end }) - let creds = req.Credentials(lori.TCPConnectAuth(h.env.root)) - let converter = PaginatedListJsonConverter[String]( - creds, _TestStringConverter) - let receiver = PaginatedResultReceiver[String]( - creds, p, converter) - receiver.failure(403, "forbidden", "auth failed") + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root)) + let converter = + PaginatedListJSONConverter[String]( + creds, _TestStringConverter) + let receiver = + PaginatedResultReceiver[String]( + creds, p, converter) + receiver.failure( + 403, "forbidden", "auth failed") class \nodoc\ _TestSearchResultReceiverSuccess is UnitTest - fun name(): String => "result-receivers/search/success" + fun name(): String => + "result-receivers/search/success" fun ref apply(h: TestHelper) => h.long_test(2_000_000_000) - let p = Promise[(SearchResults[String] | req.RequestError)] + let p = + Promise[ + (SearchResults[String] | req.RequestError)] p.next[None]( - {(result: (SearchResults[String] | req.RequestError))(h) => - match result + {(result: + (SearchResults[String] | req.RequestError)) + (h) + => + match \exhaustive\ result | let sr: SearchResults[String] => h.assert_eq[I64](42, sr.total_count) h.assert_false(sr.incomplete_results) h.assert_eq[USize](1, sr.items.size()) try - h.assert_eq[String]("result1", sr.items(0)?) + h.assert_eq[String]( + "result1", sr.items(0)?) else h.fail("Failed to access items(0)") end h.complete(true) | let e: req.RequestError => h.fail( - "Expected SearchResults, got RequestError: " - + e.message) + "Expected SearchResults, " + + "got RequestError: " + e.message) h.complete(false) end }) - let creds = req.Credentials(lori.TCPConnectAuth(h.env.root)) - let converter = PaginatedSearchJsonConverter[String]( - creds, _TestStringConverter) - let receiver = SearchResultReceiver[String]( - creds, p, converter) + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root)) + let converter = + PaginatedSearchJSONConverter[String]( + creds, _TestStringConverter) + let receiver = + SearchResultReceiver[String]( + creds, p, converter) let items_arr = JSONArray .push(JSONObject.update("value", "result1")) let envelope = JSONObject @@ -316,50 +400,77 @@ class \nodoc\ _TestSearchResultReceiverConverterError is UnitTest fun ref apply(h: TestHelper) => h.long_test(2_000_000_000) - let p = Promise[(SearchResults[String] | req.RequestError)] + let p = + Promise[ + (SearchResults[String] | req.RequestError)] p.next[None]( - {(result: (SearchResults[String] | req.RequestError))(h) => - match result + {(result: + (SearchResults[String] | req.RequestError)) + (h) + => + match \exhaustive\ result | let _: SearchResults[String] => - h.fail("Expected RequestError, got SearchResults") + h.fail( + "Expected RequestError, " + + "got SearchResults") h.complete(false) | let e: req.RequestError => h.assert_true( - e.message.contains("Unable to convert json"), - "Expected 'Unable to convert json', got: " - + e.message) + e.message.contains( + "Unable to convert json"), + "Expected 'Unable to convert json'" + + ", got: " + e.message) h.complete(true) end }) - let creds = req.Credentials(lori.TCPConnectAuth(h.env.root)) - let converter = PaginatedSearchJsonConverter[String]( - creds, _TestStringConverter) - let receiver = SearchResultReceiver[String]( - creds, p, converter) + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root)) + let converter = + PaginatedSearchJSONConverter[String]( + creds, _TestStringConverter) + let receiver = + SearchResultReceiver[String]( + creds, p, converter) receiver.success(JSONNav(JSONObject), "") class \nodoc\ _TestSearchResultReceiverFailure is UnitTest - fun name(): String => "result-receivers/search/failure" + fun name(): String => + "result-receivers/search/failure" fun ref apply(h: TestHelper) => h.long_test(2_000_000_000) - let p = Promise[(SearchResults[String] | req.RequestError)] + let p = + Promise[ + (SearchResults[String] | req.RequestError)] p.next[None]( - {(result: (SearchResults[String] | req.RequestError))(h) => - match result + {(result: + (SearchResults[String] | req.RequestError)) + (h) + => + match \exhaustive\ result | let _: SearchResults[String] => - h.fail("Expected RequestError, got SearchResults") + h.fail( + "Expected RequestError, " + + "got SearchResults") h.complete(false) | let e: req.RequestError => h.assert_eq[U16](401, e.status) - h.assert_eq[String]("unauthorized", e.response_body) - h.assert_eq[String]("bad token", e.message) + h.assert_eq[String]( + "unauthorized", e.response_body) + h.assert_eq[String]( + "bad token", e.message) h.complete(true) end }) - let creds = req.Credentials(lori.TCPConnectAuth(h.env.root)) - let converter = PaginatedSearchJsonConverter[String]( - creds, _TestStringConverter) - let receiver = SearchResultReceiver[String]( - creds, p, converter) - receiver.failure(401, "unauthorized", "bad token") + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root)) + let converter = + PaginatedSearchJSONConverter[String]( + creds, _TestStringConverter) + let receiver = + SearchResultReceiver[String]( + creds, p, converter) + receiver.failure( + 401, "unauthorized", "bad token") diff --git a/github_rest_api/_test_search_and_pagination.pony b/github_rest_api/_test_search_and_pagination.pony index 54ed002..4955b7e 100644 --- a/github_rest_api/_test_search_and_pagination.pony +++ b/github_rest_api/_test_search_and_pagination.pony @@ -13,8 +13,9 @@ class \nodoc\ _TestSearchConverterExtractsLinks is UnitTest fun ref apply(h: TestHelper) => h.long_test(2_000_000_000) let creds = req.Credentials(lori.TCPConnectAuth(h.env.root)) - let converter = PaginatedSearchJsonConverter[String]( - creds, _TestStringConverter) + let converter = + PaginatedSearchJSONConverter[String]( + creds, _TestStringConverter) let items_arr = JSONArray .push(JSONObject.update("value", "a")) .push(JSONObject.update("value", "b")) @@ -22,10 +23,11 @@ class \nodoc\ _TestSearchConverterExtractsLinks is UnitTest .update("total_count", I64(10)) .update("incomplete_results", true) .update("items", items_arr) - let link = recover val - "; rel=\"prev\", " - + "; rel=\"next\"" - end + let link = + recover val + "; rel=\"prev\", " + + "; rel=\"next\"" + end try let sr = converter(JSONNav(envelope), link, creds)? h.assert_eq[I64](10, sr.total_count) @@ -33,9 +35,11 @@ class \nodoc\ _TestSearchConverterExtractsLinks is UnitTest h.assert_eq[USize](2, sr.items.size()) h.assert_eq[String]("a", sr.items(0)?) h.assert_eq[String]("b", sr.items(1)?) - h.assert_true(sr.next_page() isnt None, + h.assert_true( + sr.next_page() isnt None, "next_page should not be None") - h.assert_true(sr.prev_page() isnt None, + h.assert_true( + sr.prev_page() isnt None, "prev_page should not be None") h.complete(true) else @@ -49,8 +53,9 @@ class \nodoc\ _TestSearchConverterNoLinks is UnitTest fun ref apply(h: TestHelper) => h.long_test(2_000_000_000) let creds = req.Credentials(lori.TCPConnectAuth(h.env.root)) - let converter = PaginatedSearchJsonConverter[String]( - creds, _TestStringConverter) + let converter = + PaginatedSearchJSONConverter[String]( + creds, _TestStringConverter) let items_arr = JSONArray .push(JSONObject.update("value", "x")) let envelope = JSONObject @@ -61,9 +66,11 @@ class \nodoc\ _TestSearchConverterNoLinks is UnitTest let sr = converter(JSONNav(envelope), "", creds)? h.assert_eq[USize](1, sr.items.size()) h.assert_eq[String]("x", sr.items(0)?) - h.assert_true(sr.next_page() is None, + h.assert_true( + sr.next_page() is None, "next_page should be None") - h.assert_true(sr.prev_page() is None, + h.assert_true( + sr.prev_page() is None, "prev_page should be None") h.complete(true) else @@ -77,23 +84,27 @@ class \nodoc\ _TestListConverterExtractsLinks is UnitTest fun ref apply(h: TestHelper) => h.long_test(2_000_000_000) let creds = req.Credentials(lori.TCPConnectAuth(h.env.root)) - let converter = PaginatedListJsonConverter[String]( - creds, _TestStringConverter) + let converter = + PaginatedListJSONConverter[String]( + creds, _TestStringConverter) let arr = JSONArray .push(JSONObject.update("value", "p")) .push(JSONObject.update("value", "q")) - let link = recover val - "; rel=\"prev\", " - + "; rel=\"next\"" - end + let link = + recover val + "; rel=\"prev\", " + + "; rel=\"next\"" + end try let pl = converter(JSONNav(arr), link, creds)? h.assert_eq[USize](2, pl.results.size()) h.assert_eq[String]("p", pl.results(0)?) h.assert_eq[String]("q", pl.results(1)?) - h.assert_true(pl.next_page() isnt None, + h.assert_true( + pl.next_page() isnt None, "next_page should not be None") - h.assert_true(pl.prev_page() isnt None, + h.assert_true( + pl.prev_page() isnt None, "prev_page should not be None") h.complete(true) else @@ -107,17 +118,20 @@ class \nodoc\ _TestListConverterNoLinks is UnitTest fun ref apply(h: TestHelper) => h.long_test(2_000_000_000) let creds = req.Credentials(lori.TCPConnectAuth(h.env.root)) - let converter = PaginatedListJsonConverter[String]( - creds, _TestStringConverter) + let converter = + PaginatedListJSONConverter[String]( + creds, _TestStringConverter) let arr = JSONArray .push(JSONObject.update("value", "z")) try let pl = converter(JSONNav(arr), "", creds)? h.assert_eq[USize](1, pl.results.size()) h.assert_eq[String]("z", pl.results(0)?) - h.assert_true(pl.next_page() is None, + h.assert_true( + pl.next_page() is None, "next_page should be None") - h.assert_true(pl.prev_page() is None, + h.assert_true( + pl.prev_page() is None, "prev_page should be None") h.complete(true) else @@ -125,27 +139,32 @@ class \nodoc\ _TestListConverterNoLinks is UnitTest h.complete(false) end -// --- Mock HTTP tests: pagination behavior --- - class \nodoc\ _TestSearchNextPageFollowsLink is UnitTest - fun name(): String => "search-pagination/search/next-page-follows-link" + fun name(): String => + "search-pagination/search/next-page-follows-link" fun ref apply(h: TestHelper) ? => h.long_test(10_000_000_000) let sslctx = _TestSSLContext(h)? let host = _TestHost() let port: String = "48115" - let page1_url = _TestUrl(host, port, "/page1") - let creds = req.Credentials( - lori.TCPConnectAuth(h.env.root) where ssl_ctx' = sslctx) - let converter = PaginatedSearchJsonConverter[String]( - creds, _TestStringConverter) + let page1_url = _TestURL(host, port, "/page1") + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root) + where ssl_ctx' = sslctx) + let converter = + PaginatedSearchJSONConverter[String]( + creds, _TestStringConverter) - let p = Promise[(SearchResults[String] | req.RequestError)] + let p = + Promise[(SearchResults[String] | req.RequestError)] p.next[None]( - {(result: (SearchResults[String] | req.RequestError))(h, creds, - converter) => - match result + {(result: + (SearchResults[String] | req.RequestError)) + (h, creds, converter) + => + match \exhaustive\ result | let sr: SearchResults[String] => try h.assert_eq[USize](1, sr.items.size()) @@ -156,29 +175,42 @@ class \nodoc\ _TestSearchNextPageFollowsLink is UnitTest h.complete(false) return end - match sr.next_page() - | let p2: Promise[(SearchResults[String] | req.RequestError)] => + match \exhaustive\ sr.next_page() + | let p2: + Promise[ + (SearchResults[String] | req.RequestError)] + => p2.next[None]( - {(result2: (SearchResults[String] | req.RequestError))(h) => - match result2 + {(result2: + (SearchResults[String] | + req.RequestError))(h) + => + match \exhaustive\ result2 | let sr2: SearchResults[String] => try - h.assert_eq[USize](1, sr2.items.size()) - h.assert_eq[String]("b", sr2.items(0)?) - h.assert_true(sr2.next_page() is None, - "page 2 next_page should be None") + h.assert_eq[USize]( + 1, sr2.items.size()) + h.assert_eq[String]( + "b", sr2.items(0)?) + h.assert_true( + sr2.next_page() is None, + "page 2 next_page should " + + "be None") h.complete(true) else - h.fail("Failed to access page 2 items") + h.fail( + "Failed to access page 2 items") h.complete(false) end | let e: req.RequestError => - h.fail("Page 2 error: " + e.message) + h.fail( + "Page 2 error: " + e.message) h.complete(false) end }) | None => - h.fail("next_page() returned None on page 1") + h.fail( + "next_page() returned None on page 1") h.complete(false) end | let e: req.RequestError => @@ -187,53 +219,74 @@ class \nodoc\ _TestSearchNextPageFollowsLink is UnitTest end }) - let page2_link = _TestUrl(host, port, "/page2") + let page2_link = _TestURL(host, port, "/page2") let responder: _Responder = {(request: String)(page2_link): String => if request.contains("GET /page2") then let body = - """{"total_count":3,"incomplete_results":false,"items":[{"value":"b"}]}""" - "HTTP/1.1 200 OK\r\n" - + "Content-Length: " + body.size().string() + "\r\n" - + "\r\n" - + body + "{\"total_count\":3," + + "\"incomplete_results\":false," + + "\"items\":[{\"value\":\"b\"}]}" + "HTTP/1.1 200 OK\r\n" + + "Content-Length: " + + body.size().string() + "\r\n" + + "\r\n" + + body else let body = - """{"total_count":3,"incomplete_results":false,"items":[{"value":"a"}]}""" - "HTTP/1.1 200 OK\r\n" - + "Content-Length: " + body.size().string() + "\r\n" - + "Link: <" + page2_link + ">; rel=\"next\"\r\n" - + "\r\n" - + body + "{\"total_count\":3," + + "\"incomplete_results\":false," + + "\"items\":[{\"value\":\"a\"}]}" + "HTTP/1.1 200 OK\r\n" + + "Content-Length: " + + body.size().string() + "\r\n" + + "Link: <" + page2_link + + ">; rel=\"next\"\r\n" + + "\r\n" + + body end } val - let receiver = SearchResultReceiver[String](creds, p, converter) - let listener = _MockHTTPListener(h, port, sslctx, responder, - {()(creds, page1_url, receiver) => - LinkedJsonRequester(creds, page1_url, receiver) - } val) + let receiver = + SearchResultReceiver[String](creds, p, converter) + let listener = + _MockHTTPListener( + h, + port, + sslctx, + responder, + {()(creds, page1_url, receiver) => + LinkedJSONRequester( + creds, page1_url, receiver) + } val) h.dispose_when_done(listener) class \nodoc\ _TestSearchPrevPageFollowsLink is UnitTest - fun name(): String => "search-pagination/search/prev-page-follows-link" + fun name(): String => + "search-pagination/search/prev-page-follows-link" fun ref apply(h: TestHelper) ? => h.long_test(10_000_000_000) let sslctx = _TestSSLContext(h)? let host = _TestHost() let port: String = "48116" - let page2_url = _TestUrl(host, port, "/page2") - let creds = req.Credentials( - lori.TCPConnectAuth(h.env.root) where ssl_ctx' = sslctx) - let converter = PaginatedSearchJsonConverter[String]( - creds, _TestStringConverter) + let page2_url = _TestURL(host, port, "/page2") + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root) + where ssl_ctx' = sslctx) + let converter = + PaginatedSearchJSONConverter[String]( + creds, _TestStringConverter) - let p = Promise[(SearchResults[String] | req.RequestError)] + let p = + Promise[(SearchResults[String] | req.RequestError)] p.next[None]( - {(result: (SearchResults[String] | req.RequestError))(h, creds, - converter) => - match result + {(result: + (SearchResults[String] | req.RequestError)) + (h, creds, converter) + => + match \exhaustive\ result | let sr: SearchResults[String] => try h.assert_eq[USize](1, sr.items.size()) @@ -243,29 +296,42 @@ class \nodoc\ _TestSearchPrevPageFollowsLink is UnitTest h.complete(false) return end - match sr.prev_page() - | let p1: Promise[(SearchResults[String] | req.RequestError)] => + match \exhaustive\ sr.prev_page() + | let p1: + Promise[ + (SearchResults[String] | req.RequestError)] + => p1.next[None]( - {(result2: (SearchResults[String] | req.RequestError))(h) => - match result2 + {(result2: + (SearchResults[String] | + req.RequestError))(h) + => + match \exhaustive\ result2 | let sr2: SearchResults[String] => try - h.assert_eq[USize](1, sr2.items.size()) - h.assert_eq[String]("a", sr2.items(0)?) - h.assert_true(sr2.prev_page() is None, - "page 1 prev_page should be None") + h.assert_eq[USize]( + 1, sr2.items.size()) + h.assert_eq[String]( + "a", sr2.items(0)?) + h.assert_true( + sr2.prev_page() is None, + "page 1 prev_page should " + + "be None") h.complete(true) else - h.fail("Failed to access page 1 items") + h.fail( + "Failed to access page 1 items") h.complete(false) end | let e: req.RequestError => - h.fail("Page 1 error: " + e.message) + h.fail( + "Page 1 error: " + e.message) h.complete(false) end }) | None => - h.fail("prev_page() returned None on page 2") + h.fail( + "prev_page() returned None on page 2") h.complete(false) end | let e: req.RequestError => @@ -274,85 +340,122 @@ class \nodoc\ _TestSearchPrevPageFollowsLink is UnitTest end }) - let page1_link = _TestUrl(host, port, "/page1") + let page1_link = _TestURL(host, port, "/page1") let responder: _Responder = {(request: String)(page1_link): String => if request.contains("GET /page1") then let body = - """{"total_count":3,"incomplete_results":false,"items":[{"value":"a"}]}""" - "HTTP/1.1 200 OK\r\n" - + "Content-Length: " + body.size().string() + "\r\n" - + "\r\n" - + body + "{\"total_count\":3," + + "\"incomplete_results\":false," + + "\"items\":[{\"value\":\"a\"}]}" + "HTTP/1.1 200 OK\r\n" + + "Content-Length: " + + body.size().string() + "\r\n" + + "\r\n" + + body else let body = - """{"total_count":3,"incomplete_results":false,"items":[{"value":"b"}]}""" - "HTTP/1.1 200 OK\r\n" - + "Content-Length: " + body.size().string() + "\r\n" - + "Link: <" + page1_link + ">; rel=\"prev\"\r\n" - + "\r\n" - + body + "{\"total_count\":3," + + "\"incomplete_results\":false," + + "\"items\":[{\"value\":\"b\"}]}" + "HTTP/1.1 200 OK\r\n" + + "Content-Length: " + + body.size().string() + "\r\n" + + "Link: <" + page1_link + + ">; rel=\"prev\"\r\n" + + "\r\n" + + body end } val - let receiver = SearchResultReceiver[String](creds, p, converter) - let listener = _MockHTTPListener(h, port, sslctx, responder, - {()(creds, page2_url, receiver) => - LinkedJsonRequester(creds, page2_url, receiver) - } val) + let receiver = + SearchResultReceiver[String](creds, p, converter) + let listener = + _MockHTTPListener( + h, + port, + sslctx, + responder, + {()(creds, page2_url, receiver) => + LinkedJSONRequester( + creds, page2_url, receiver) + } val) h.dispose_when_done(listener) class \nodoc\ _TestListNextPageFollowsLink is UnitTest - fun name(): String => "search-pagination/list/next-page-follows-link" + fun name(): String => + "search-pagination/list/next-page-follows-link" fun ref apply(h: TestHelper) ? => h.long_test(10_000_000_000) let sslctx = _TestSSLContext(h)? let host = _TestHost() let port: String = "48117" - let page1_url = _TestUrl(host, port, "/page1") - let creds = req.Credentials( - lori.TCPConnectAuth(h.env.root) where ssl_ctx' = sslctx) - let converter = PaginatedListJsonConverter[String]( - creds, _TestStringConverter) + let page1_url = _TestURL(host, port, "/page1") + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root) + where ssl_ctx' = sslctx) + let converter = + PaginatedListJSONConverter[String]( + creds, _TestStringConverter) - let p = Promise[(PaginatedList[String] | req.RequestError)] + let p = + Promise[(PaginatedList[String] | req.RequestError)] p.next[None]( - {(result: (PaginatedList[String] | req.RequestError))(h, creds, - converter) => - match result + {(result: + (PaginatedList[String] | req.RequestError)) + (h, creds, converter) + => + match \exhaustive\ result | let pl: PaginatedList[String] => try h.assert_eq[USize](1, pl.results.size()) h.assert_eq[String]("x", pl.results(0)?) else - h.fail("Failed to access page 1 results") + h.fail( + "Failed to access page 1 results") h.complete(false) return end - match pl.next_page() - | let p2: Promise[(PaginatedList[String] | req.RequestError)] => + match \exhaustive\ pl.next_page() + | let p2: + Promise[ + (PaginatedList[String] | + req.RequestError)] + => p2.next[None]( - {(result2: (PaginatedList[String] | req.RequestError))(h) => - match result2 + {(result2: + (PaginatedList[String] | + req.RequestError))(h) + => + match \exhaustive\ result2 | let pl2: PaginatedList[String] => try - h.assert_eq[USize](1, pl2.results.size()) - h.assert_eq[String]("y", pl2.results(0)?) - h.assert_true(pl2.next_page() is None, - "page 2 next_page should be None") + h.assert_eq[USize]( + 1, pl2.results.size()) + h.assert_eq[String]( + "y", pl2.results(0)?) + h.assert_true( + pl2.next_page() is None, + "page 2 next_page should " + + "be None") h.complete(true) else - h.fail("Failed to access page 2 results") + h.fail( + "Failed to access " + + "page 2 results") h.complete(false) end | let e: req.RequestError => - h.fail("Page 2 error: " + e.message) + h.fail( + "Page 2 error: " + e.message) h.complete(false) end }) | None => - h.fail("next_page() returned None on page 1") + h.fail( + "next_page() returned None on page 1") h.complete(false) end | let e: req.RequestError => @@ -361,83 +464,117 @@ class \nodoc\ _TestListNextPageFollowsLink is UnitTest end }) - let page2_link = _TestUrl(host, port, "/page2") + let page2_link = _TestURL(host, port, "/page2") let responder: _Responder = {(request: String)(page2_link): String => if request.contains("GET /page2") then let body = """[{"value":"y"}]""" - "HTTP/1.1 200 OK\r\n" - + "Content-Length: " + body.size().string() + "\r\n" - + "\r\n" - + body + "HTTP/1.1 200 OK\r\n" + + "Content-Length: " + + body.size().string() + "\r\n" + + "\r\n" + + body else let body = """[{"value":"x"}]""" - "HTTP/1.1 200 OK\r\n" - + "Content-Length: " + body.size().string() + "\r\n" - + "Link: <" + page2_link + ">; rel=\"next\"\r\n" - + "\r\n" - + body + "HTTP/1.1 200 OK\r\n" + + "Content-Length: " + + body.size().string() + "\r\n" + + "Link: <" + page2_link + + ">; rel=\"next\"\r\n" + + "\r\n" + + body end } val - let receiver = PaginatedResultReceiver[String](creds, p, converter) - let listener = _MockHTTPListener(h, port, sslctx, responder, - {()(creds, page1_url, receiver) => - LinkedJsonRequester(creds, page1_url, receiver) - } val) + let receiver = + PaginatedResultReceiver[String]( + creds, p, converter) + let listener = + _MockHTTPListener( + h, + port, + sslctx, + responder, + {()(creds, page1_url, receiver) => + LinkedJSONRequester( + creds, page1_url, receiver) + } val) h.dispose_when_done(listener) class \nodoc\ _TestListPrevPageFollowsLink is UnitTest - fun name(): String => "search-pagination/list/prev-page-follows-link" + fun name(): String => + "search-pagination/list/prev-page-follows-link" fun ref apply(h: TestHelper) ? => h.long_test(10_000_000_000) let sslctx = _TestSSLContext(h)? let host = _TestHost() let port: String = "48118" - let page2_url = _TestUrl(host, port, "/page2") - let creds = req.Credentials( - lori.TCPConnectAuth(h.env.root) where ssl_ctx' = sslctx) - let converter = PaginatedListJsonConverter[String]( - creds, _TestStringConverter) + let page2_url = _TestURL(host, port, "/page2") + let creds = + req.Credentials( + lori.TCPConnectAuth(h.env.root) + where ssl_ctx' = sslctx) + let converter = + PaginatedListJSONConverter[String]( + creds, _TestStringConverter) - let p = Promise[(PaginatedList[String] | req.RequestError)] + let p = + Promise[(PaginatedList[String] | req.RequestError)] p.next[None]( - {(result: (PaginatedList[String] | req.RequestError))(h, creds, - converter) => - match result + {(result: + (PaginatedList[String] | req.RequestError)) + (h, creds, converter) + => + match \exhaustive\ result | let pl: PaginatedList[String] => try h.assert_eq[USize](1, pl.results.size()) h.assert_eq[String]("y", pl.results(0)?) else - h.fail("Failed to access page 2 results") + h.fail( + "Failed to access page 2 results") h.complete(false) return end - match pl.prev_page() - | let p1: Promise[(PaginatedList[String] | req.RequestError)] => + match \exhaustive\ pl.prev_page() + | let p1: + Promise[ + (PaginatedList[String] | + req.RequestError)] + => p1.next[None]( - {(result2: (PaginatedList[String] | req.RequestError))(h) => - match result2 + {(result2: + (PaginatedList[String] | + req.RequestError))(h) + => + match \exhaustive\ result2 | let pl2: PaginatedList[String] => try - h.assert_eq[USize](1, pl2.results.size()) - h.assert_eq[String]("x", pl2.results(0)?) - h.assert_true(pl2.prev_page() is None, - "page 1 prev_page should be None") + h.assert_eq[USize]( + 1, pl2.results.size()) + h.assert_eq[String]( + "x", pl2.results(0)?) + h.assert_true( + pl2.prev_page() is None, + "page 1 prev_page should " + + "be None") h.complete(true) else - h.fail("Failed to access page 1 results") + h.fail( + "Failed to access " + + "page 1 results") h.complete(false) end | let e: req.RequestError => - h.fail("Page 1 error: " + e.message) + h.fail( + "Page 1 error: " + e.message) h.complete(false) end }) | None => - h.fail("prev_page() returned None on page 2") + h.fail( + "prev_page() returned None on page 2") h.complete(false) end | let e: req.RequestError => @@ -446,28 +583,39 @@ class \nodoc\ _TestListPrevPageFollowsLink is UnitTest end }) - let page1_link = _TestUrl(host, port, "/page1") + let page1_link = _TestURL(host, port, "/page1") let responder: _Responder = {(request: String)(page1_link): String => if request.contains("GET /page1") then let body = """[{"value":"x"}]""" - "HTTP/1.1 200 OK\r\n" - + "Content-Length: " + body.size().string() + "\r\n" - + "\r\n" - + body + "HTTP/1.1 200 OK\r\n" + + "Content-Length: " + + body.size().string() + "\r\n" + + "\r\n" + + body else let body = """[{"value":"y"}]""" - "HTTP/1.1 200 OK\r\n" - + "Content-Length: " + body.size().string() + "\r\n" - + "Link: <" + page1_link + ">; rel=\"prev\"\r\n" - + "\r\n" - + body + "HTTP/1.1 200 OK\r\n" + + "Content-Length: " + + body.size().string() + "\r\n" + + "Link: <" + page1_link + + ">; rel=\"prev\"\r\n" + + "\r\n" + + body end } val - let receiver = PaginatedResultReceiver[String](creds, p, converter) - let listener = _MockHTTPListener(h, port, sslctx, responder, - {()(creds, page2_url, receiver) => - LinkedJsonRequester(creds, page2_url, receiver) - } val) + let receiver = + PaginatedResultReceiver[String]( + creds, p, converter) + let listener = + _MockHTTPListener( + h, + port, + sslctx, + responder, + {()(creds, page2_url, receiver) => + LinkedJSONRequester( + creds, page2_url, receiver) + } val) h.dispose_when_done(listener) diff --git a/github_rest_api/asset.pony b/github_rest_api/asset.pony index 94e1c4b..29470a8 100644 --- a/github_rest_api/asset.pony +++ b/github_rest_api/asset.pony @@ -7,7 +7,6 @@ class val Asset its name, size, download count, and the browser download URL. """ let _creds: req.Credentials - let id: I64 let node_id: String let name: String @@ -19,7 +18,6 @@ class val Asset let download_count: I64 let created_at: String let updated_at: String - let url: String let browser_download_url: String @@ -53,16 +51,19 @@ class val Asset url = url' browser_download_url = browser_download_url' -primitive AssetJsonConverter is req.JSONConverter[Asset] +primitive AssetJSONConverter is req.JSONConverter[Asset] """ Converts a JSON object into an Asset. """ fun apply(json: JSONNav, creds: req.Credentials): Asset ? => + """ + Parses the JSON representation of a release asset. + """ let id = json("id").as_i64()? let node_id = json("node_id").as_string()? let name = json("name").as_string()? let label = JSONNavUtil.string_or_none(json("label"))? - let uploader = UserJsonConverter(json("uploader"), creds)? + let uploader = UserJSONConverter(json("uploader"), creds)? let content_type = json("content_type").as_string()? let state = json("state").as_string()? let size = json("size").as_i64()? @@ -72,7 +73,8 @@ primitive AssetJsonConverter is req.JSONConverter[Asset] let url = json("url").as_string()? let browser_download_url = json("browser_download_url").as_string()? - Asset(creds, + Asset( + creds, id, node_id, name, diff --git a/github_rest_api/commit.pony b/github_rest_api/commit.pony index 2112fca..90a1a4a 100644 --- a/github_rest_api/commit.pony +++ b/github_rest_api/commit.pony @@ -47,41 +47,55 @@ primitive GetCommit "https://api.github.com/repos{/owner}{/repo}/commits{/sha}") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("owner", owner) - .>set("repo", repo) - .>set("sha", sha) + .> set("owner", owner) + .> set("repo", repo) + .> set("sha", sha) let u: String val = tpl.expand(vars) by_url(u, creds) | let e: ut.URITemplateParseError => - Promise[CommitOrError].>apply(req.RequestError(where message' = e.message)) + Promise[CommitOrError] .> apply( + req.RequestError(where message' = e.message)) end - fun by_url(url: String, creds: req.Credentials): Promise[CommitOrError] => + fun by_url( + url: String, + creds: req.Credentials): Promise[CommitOrError] + => + """ + Fetches a commit by its full API URL. + """ let p = Promise[CommitOrError] - let receiver = req.ResultReceiver[Commit](creds, p, CommitJsonConverter) + let receiver = + req.ResultReceiver[Commit](creds, p, CommitJSONConverter) req.JSONRequester.get(creds, url, receiver) p -primitive CommitJsonConverter is req.JSONConverter[Commit] +primitive CommitJSONConverter is req.JSONConverter[Commit] """ Converts a JSON object from the commits API into a Commit. """ fun apply(json: JSONNav, creds: req.Credentials): Commit ? => + """ + Parses the JSON representation of a commit. + """ let sha = json("sha").as_string()? let files = recover trn Array[CommitFile] end for f in json("files").as_array()?.values() do - let file = CommitFileJsonConverter(JSONNav(f), creds)? + let file = + CommitFileJSONConverter(JSONNav(f), creds)? files.push(file) end - let git_commit = GitCommitJsonConverter(json("commit"), creds)? + let git_commit = + GitCommitJSONConverter(json("commit"), creds)? let url = json("url").as_string()? let html_url = json("html_url").as_string()? let comments_url = json("comments_url").as_string()? - Commit(creds, + Commit( + creds, sha, consume files, git_commit, diff --git a/github_rest_api/commit_file.pony b/github_rest_api/commit_file.pony index ef021f4..6ea0655 100644 --- a/github_rest_api/commit_file.pony +++ b/github_rest_api/commit_file.pony @@ -21,13 +21,16 @@ class val CommitFile status = status' filename = filename' -primitive CommitFileJsonConverter is req.JSONConverter[CommitFile] +primitive CommitFileJSONConverter is req.JSONConverter[CommitFile] """ Converts a JSON object into a CommitFile. """ fun apply(json: JSONNav, creds: req.Credentials): CommitFile ? => + """ + Parses the JSON representation of a changed file in a commit. + """ let sha = json("sha").as_string()? let status = json("status").as_string()? let filename = json("filename").as_string()? diff --git a/github_rest_api/gist.pony b/github_rest_api/gist.pony index 94d452d..36d805b 100644 --- a/github_rest_api/gist.pony +++ b/github_rest_api/gist.pony @@ -80,12 +80,14 @@ class val Gist fun update_gist( update_files: Array[(String, GistFileUpdate)] val, - new_description: (String | None) = None): Promise[GistOrError] + new_description: (String | None) = None) + : Promise[GistOrError] => """ Updates this gist's files and/or description. """ - UpdateGist.by_url(url, update_files, _creds, new_description) + UpdateGist.by_url( + url, update_files, _creds, new_description) fun delete_gist(): Promise[req.DeletedOrError] => """ @@ -145,7 +147,9 @@ class val Gist recover val url + "/star" end, _creds) - fun create_comment(body: String): Promise[GistCommentOrError] => + fun create_comment(body: String) + : Promise[GistCommentOrError] + => """ Creates a new comment on this gist. """ @@ -166,20 +170,28 @@ primitive GetGist fun apply(gist_id: String, creds: req.Credentials): Promise[GistOrError] => - match \exhaustive\ ut.URITemplateParse("https://api.github.com/gists{/gist_id}") + match \exhaustive\ ut.URITemplateParse( + "https://api.github.com/gists{/gist_id}") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("gist_id", gist_id) + .> set("gist_id", gist_id) let u: String val = tpl.expand(vars) by_url(u, creds) | let e: ut.URITemplateParseError => - Promise[GistOrError].>apply( + Promise[GistOrError] .> apply( req.RequestError(where message' = e.message)) end - fun by_url(url: String, creds: req.Credentials): Promise[GistOrError] => + fun by_url(url: String, + creds: req.Credentials): Promise[GistOrError] + => + """ + Fetches a gist by its direct API URL. + """ let p = Promise[GistOrError] - let r = req.ResultReceiver[Gist](creds, p, GistJsonConverter) + let r = + req.ResultReceiver[Gist]( + creds, p, GistJSONConverter) req.JSONRequester.get(creds, url, r) p @@ -194,7 +206,8 @@ primitive CreateGist description: (String | None) = None, is_public: Bool = false): Promise[GistOrError] => - by_url("https://api.github.com/gists", + by_url( + "https://api.github.com/gists", files, creds, description, @@ -206,13 +219,20 @@ primitive CreateGist description: (String | None) = None, is_public: Bool = false): Promise[GistOrError] => + """ + Creates a gist at the given API URL. + """ let p = Promise[GistOrError] - let r = req.ResultReceiver[Gist](creds, p, GistJsonConverter) + let r = + req.ResultReceiver[Gist]( + creds, p, GistJSONConverter) var files_obj = JSONObject for (name, content) in files.values() do - files_obj = files_obj.update(name, - JSONObject.update("content", content)) + files_obj = + files_obj.update( + name, + JSONObject.update("content", content)) end var obj = JSONObject @@ -236,37 +256,50 @@ primitive UpdateGist fun apply(gist_id: String, files: Array[(String, GistFileUpdate)] val, creds: req.Credentials, - description: (String | None) = None): Promise[GistOrError] + description: (String | None) = None) + : Promise[GistOrError] => - match \exhaustive\ ut.URITemplateParse("https://api.github.com/gists{/gist_id}") + match \exhaustive\ ut.URITemplateParse( + "https://api.github.com/gists{/gist_id}") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("gist_id", gist_id) + .> set("gist_id", gist_id) let u: String val = tpl.expand(vars) by_url(u, files, creds, description) | let e: ut.URITemplateParseError => - Promise[GistOrError].>apply( + Promise[GistOrError] .> apply( req.RequestError(where message' = e.message)) end fun by_url(url: String, files: Array[(String, GistFileUpdate)] val, creds: req.Credentials, - description: (String | None) = None): Promise[GistOrError] + description: (String | None) = None) + : Promise[GistOrError] => + """ + Updates a gist at the given API URL. + """ let p = Promise[GistOrError] - let r = req.ResultReceiver[Gist](creds, p, GistJsonConverter) + let r = + req.ResultReceiver[Gist]( + creds, p, GistJSONConverter) var files_obj = JSONObject for (name, update) in files.values() do match \exhaustive\ update | let edit: GistFileEdit => - files_obj = files_obj.update(name, - JSONObject.update("content", edit.content)) + files_obj = + files_obj.update( + name, + JSONObject.update("content", edit.content)) | let rename: GistFileRename => - var entry = JSONObject.update("filename", rename.filename) + var entry = + JSONObject.update( + "filename", rename.filename) match rename.content - | let c: String => entry = entry.update("content", c) + | let c: String => + entry = entry.update("content", c) end files_obj = files_obj.update(name, entry) | GistFileDelete => @@ -276,11 +309,13 @@ primitive UpdateGist var obj = JSONObject.update("files", files_obj) match description - | let d: String => obj = obj.update("description", d) + | let d: String => + obj = obj.update("description", d) end let json = obj.print() - req.JSONRequester.patch(creds, url, consume json, r) + req.JSONRequester.patch( + creds, url, consume json, r) p primitive DeleteGist @@ -290,20 +325,24 @@ primitive DeleteGist fun apply(gist_id: String, creds: req.Credentials): Promise[req.DeletedOrError] => - match \exhaustive\ ut.URITemplateParse("https://api.github.com/gists{/gist_id}") + match \exhaustive\ ut.URITemplateParse( + "https://api.github.com/gists{/gist_id}") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("gist_id", gist_id) + .> set("gist_id", gist_id) let u: String val = tpl.expand(vars) by_url(u, creds) | let e: ut.URITemplateParseError => - Promise[req.DeletedOrError].>apply( + Promise[req.DeletedOrError] .> apply( req.RequestError(where message' = e.message)) end fun by_url(url: String, creds: req.Credentials): Promise[req.DeletedOrError] => + """ + Deletes a gist at the given API URL. + """ let p = Promise[req.DeletedOrError] let r = req.DeletedResultReceiver(p) @@ -317,7 +356,8 @@ primitive GetUserGists fun apply(creds: req.Credentials) : Promise[(PaginatedList[Gist] | req.RequestError)] => - _GetPaginatedGists.by_url("https://api.github.com/gists", creds) + _GetPaginatedGists.by_url( + "https://api.github.com/gists", creds) primitive GetPublicGists """ @@ -326,7 +366,8 @@ primitive GetPublicGists fun apply(creds: req.Credentials) : Promise[(PaginatedList[Gist] | req.RequestError)] => - _GetPaginatedGists.by_url("https://api.github.com/gists/public", creds) + _GetPaginatedGists.by_url( + "https://api.github.com/gists/public", creds) primitive GetStarredGists """ @@ -335,7 +376,8 @@ primitive GetStarredGists fun apply(creds: req.Credentials) : Promise[(PaginatedList[Gist] | req.RequestError)] => - _GetPaginatedGists.by_url("https://api.github.com/gists/starred", creds) + _GetPaginatedGists.by_url( + "https://api.github.com/gists/starred", creds) primitive GetUsernameGists """ @@ -349,11 +391,12 @@ primitive GetUsernameGists "https://api.github.com/users{/username}/gists") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("username", username) + .> set("username", username) let u: String val = tpl.expand(vars) _GetPaginatedGists.by_url(u, creds) | let e: ut.URITemplateParseError => - Promise[(PaginatedList[Gist] | req.RequestError)].>apply( + Promise[(PaginatedList[Gist] | + req.RequestError)] .> apply( req.RequestError(where message' = e.message)) end @@ -369,12 +412,12 @@ primitive GetGistRevision "https://api.github.com/gists{/gist_id}{/sha}") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("gist_id", gist_id) - .>set("sha", sha) + .> set("gist_id", gist_id) + .> set("sha", sha) let u: String val = tpl.expand(vars) GetGist.by_url(u, creds) | let e: ut.URITemplateParseError => - Promise[GistOrError].>apply( + Promise[GistOrError] .> apply( req.RequestError(where message' = e.message)) end @@ -389,19 +432,24 @@ primitive ForkGist "https://api.github.com/gists{/gist_id}/forks") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("gist_id", gist_id) + .> set("gist_id", gist_id) let u: String val = tpl.expand(vars) by_url(u, creds) | let e: ut.URITemplateParseError => - Promise[GistOrError].>apply( + Promise[GistOrError] .> apply( req.RequestError(where message' = e.message)) end fun by_url(url: String, creds: req.Credentials): Promise[GistOrError] => + """ + Forks a gist at the given API URL. + """ let p = Promise[GistOrError] - let r = req.ResultReceiver[Gist](creds, p, GistJsonConverter) + let r = + req.ResultReceiver[Gist]( + creds, p, GistJSONConverter) req.JSONRequester.post(creds, url, "", r) p @@ -418,11 +466,12 @@ primitive GetGistForks "https://api.github.com/gists{/gist_id}/forks") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("gist_id", gist_id) + .> set("gist_id", gist_id) let u: String val = tpl.expand(vars) _GetPaginatedGists.by_url(u, creds) | let e: ut.URITemplateParseError => - Promise[(PaginatedList[Gist] | req.RequestError)].>apply( + Promise[(PaginatedList[Gist] | + req.RequestError)] .> apply( req.RequestError(where message' = e.message)) end @@ -438,11 +487,12 @@ primitive GetGistCommits "https://api.github.com/gists{/gist_id}/commits") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("gist_id", gist_id) + .> set("gist_id", gist_id) let u: String val = tpl.expand(vars) by_url(u, creds) | let e: ut.URITemplateParseError => - Promise[(PaginatedList[GistCommit] | req.RequestError)].>apply( + Promise[(PaginatedList[GistCommit] | + req.RequestError)] .> apply( req.RequestError(where message' = e.message)) end @@ -450,12 +500,19 @@ primitive GetGistCommits creds: req.Credentials) : Promise[(PaginatedList[GistCommit] | req.RequestError)] => - let gc = GistCommitJsonConverter - let plc = PaginatedListJsonConverter[GistCommit](creds, gc) - let p = Promise[(PaginatedList[GistCommit] | req.RequestError)] - let r = PaginatedResultReceiver[GistCommit](creds, p, plc) - - LinkedJsonRequester(creds, url, r) + """ + Lists gist commits at the given API URL. + """ + let gc = GistCommitJSONConverter + let plc = + PaginatedListJSONConverter[GistCommit](creds, gc) + let p = + Promise[(PaginatedList[GistCommit] | + req.RequestError)] + let r = + PaginatedResultReceiver[GistCommit](creds, p, plc) + + LinkedJSONRequester(creds, url, r) p primitive StarGist @@ -469,17 +526,20 @@ primitive StarGist "https://api.github.com/gists{/gist_id}/star") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("gist_id", gist_id) + .> set("gist_id", gist_id) let u: String val = tpl.expand(vars) by_url(u, creds) | let e: ut.URITemplateParseError => - Promise[req.DeletedOrError].>apply( + Promise[req.DeletedOrError] .> apply( req.RequestError(where message' = e.message)) end fun by_url(url: String, creds: req.Credentials): Promise[req.DeletedOrError] => + """ + Stars a gist at the given API URL. + """ let p = Promise[req.DeletedOrError] let r = req.DeletedResultReceiver(p) @@ -497,17 +557,20 @@ primitive UnstarGist "https://api.github.com/gists{/gist_id}/star") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("gist_id", gist_id) + .> set("gist_id", gist_id) let u: String val = tpl.expand(vars) by_url(u, creds) | let e: ut.URITemplateParseError => - Promise[req.DeletedOrError].>apply( + Promise[req.DeletedOrError] .> apply( req.RequestError(where message' = e.message)) end fun by_url(url: String, creds: req.Credentials): Promise[req.DeletedOrError] => + """ + Unstars a gist at the given API URL. + """ let p = Promise[req.DeletedOrError] let r = req.DeletedResultReceiver(p) @@ -526,17 +589,20 @@ primitive CheckGistStar "https://api.github.com/gists{/gist_id}/star") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("gist_id", gist_id) + .> set("gist_id", gist_id) let u: String val = tpl.expand(vars) by_url(u, creds) | let e: ut.URITemplateParseError => - Promise[req.BoolOrError].>apply( + Promise[req.BoolOrError] .> apply( req.RequestError(where message' = e.message)) end fun by_url(url: String, creds: req.Credentials): Promise[req.BoolOrError] => + """ + Checks gist star status at the given API URL. + """ let p = Promise[req.BoolOrError] let r = req.BoolResultReceiver(p) @@ -552,37 +618,53 @@ primitive _GetPaginatedGists creds: req.Credentials) : Promise[(PaginatedList[Gist] | req.RequestError)] => - let gc = GistJsonConverter - let plc = PaginatedListJsonConverter[Gist](creds, gc) - let p = Promise[(PaginatedList[Gist] | req.RequestError)] - let r = PaginatedResultReceiver[Gist](creds, p, plc) - - LinkedJsonRequester(creds, url, r) + let gc = GistJSONConverter + let plc = + PaginatedListJSONConverter[Gist](creds, gc) + let p = + Promise[(PaginatedList[Gist] | req.RequestError)] + let r = + PaginatedResultReceiver[Gist](creds, p, plc) + + LinkedJSONRequester(creds, url, r) p -primitive GistJsonConverter is req.JSONConverter[Gist] +primitive GistJSONConverter is req.JSONConverter[Gist] """ Converts a JSON object from the GitHub gist API into a Gist. Handles the - files object by iterating its key-value pairs and converting each value with - GistFileJsonConverter. + files object by iterating its key-value pairs and converting each value + with GistFileJSONConverter. """ fun apply(json: JSONNav, creds: req.Credentials): Gist ? => + """ + Converts a JSON object into a Gist. + """ let id = json("id").as_string()? let node_id = json("node_id").as_string()? - let description = JSONNavUtil.string_or_none(json("description"))? + let description = + JSONNavUtil.string_or_none(json("description"))? let public = json("public").as_bool()? - let owner = try UserJsonConverter(json("owner"), creds)? else None end - let user = try UserJsonConverter(json("user"), creds)? else None end + let owner = + try UserJSONConverter(json("owner"), creds)? + else None + end + let user = + try UserJSONConverter(json("user"), creds)? + else None + end let files = recover trn Array[(String, GistFile)] end for (name, value) in json("files").as_object()?.pairs() do - let gf = GistFileJsonConverter(JSONNav(value), creds)? + let gf = + GistFileJSONConverter(JSONNav(value), creds)? files.push((name, gf)) end let comments_count = json("comments").as_i64()? let comments_enabled = - try json("comments_enabled").as_bool()? else true end + try json("comments_enabled").as_bool()? + else true + end let truncated = json("truncated").as_bool()? let created_at = json("created_at").as_string()? let updated_at = json("updated_at").as_string()? @@ -591,11 +673,15 @@ primitive GistJsonConverter is req.JSONConverter[Gist] let html_url = json("html_url").as_string()? let forks_url = json("forks_url").as_string()? let commits_url = json("commits_url").as_string()? - let comments_url = json("comments_url").as_string()? - let git_pull_url = json("git_pull_url").as_string()? - let git_push_url = json("git_push_url").as_string()? - - Gist(creds, + let comments_url = + json("comments_url").as_string()? + let git_pull_url = + json("git_pull_url").as_string()? + let git_push_url = + json("git_push_url").as_string()? + + Gist( + creds, id, node_id, description, diff --git a/github_rest_api/gist_comment.pony b/github_rest_api/gist_comment.pony index b4f18cb..4159b74 100644 --- a/github_rest_api/gist_comment.pony +++ b/github_rest_api/gist_comment.pony @@ -64,22 +64,27 @@ primitive GetGistComment "https://api.github.com/gists{/gist_id}/comments{/comment_id}") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("gist_id", gist_id) - .>set("comment_id", comment_id.string()) + .> set("gist_id", gist_id) + .> set("comment_id", comment_id.string()) let u: String val = tpl.expand(vars) by_url(u, creds) | let e: ut.URITemplateParseError => - Promise[GistCommentOrError].>apply( + Promise[GistCommentOrError] .> apply( req.RequestError(where message' = e.message)) end fun by_url(url: String, creds: req.Credentials): Promise[GistCommentOrError] => + """ + Fetches a gist comment by its direct API URL. + """ let p = Promise[GistCommentOrError] - let r = req.ResultReceiver[GistComment](creds, - p, - GistCommentJsonConverter) + let r = + req.ResultReceiver[GistComment]( + creds, + p, + GistCommentJSONConverter) req.JSONRequester.get(creds, url, r) p @@ -96,11 +101,12 @@ primitive GetGistComments "https://api.github.com/gists{/gist_id}/comments") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("gist_id", gist_id) + .> set("gist_id", gist_id) let u: String val = tpl.expand(vars) by_url(u, creds) | let e: ut.URITemplateParseError => - Promise[(PaginatedList[GistComment] | req.RequestError)].>apply( + Promise[(PaginatedList[GistComment] | + req.RequestError)] .> apply( req.RequestError(where message' = e.message)) end @@ -108,12 +114,18 @@ primitive GetGistComments creds: req.Credentials) : Promise[(PaginatedList[GistComment] | req.RequestError)] => - let gc = GistCommentJsonConverter - let plc = PaginatedListJsonConverter[GistComment](creds, gc) - let p = Promise[(PaginatedList[GistComment] | req.RequestError)] - let r = PaginatedResultReceiver[GistComment](creds, p, plc) + """ + Fetches gist comments by their direct API URL. + """ + let gc = GistCommentJSONConverter + let plc = + PaginatedListJSONConverter[GistComment](creds, gc) + let p = + Promise[(PaginatedList[GistComment] | req.RequestError)] + let r = + PaginatedResultReceiver[GistComment](creds, p, plc) - LinkedJsonRequester(creds, url, r) + LinkedJSONRequester(creds, url, r) p primitive CreateGistComment @@ -128,11 +140,11 @@ primitive CreateGistComment "https://api.github.com/gists{/gist_id}/comments") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("gist_id", gist_id) + .> set("gist_id", gist_id) let u: String val = tpl.expand(vars) by_url(u, body, creds) | let e: ut.URITemplateParseError => - Promise[GistCommentOrError].>apply( + Promise[GistCommentOrError] .> apply( req.RequestError(where message' = e.message)) end @@ -140,10 +152,15 @@ primitive CreateGistComment body: String, creds: req.Credentials): Promise[GistCommentOrError] => + """ + Creates a gist comment at the given API URL. + """ let p = Promise[GistCommentOrError] - let r = req.ResultReceiver[GistComment](creds, - p, - GistCommentJsonConverter) + let r = + req.ResultReceiver[GistComment]( + creds, + p, + GistCommentJSONConverter) let json = JSONObject.update("body", body).print() req.JSONRequester.post(creds, url, consume json, r) @@ -162,12 +179,12 @@ primitive UpdateGistComment "https://api.github.com/gists{/gist_id}/comments{/comment_id}") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("gist_id", gist_id) - .>set("comment_id", comment_id.string()) + .> set("gist_id", gist_id) + .> set("comment_id", comment_id.string()) let u: String val = tpl.expand(vars) by_url(u, body, creds) | let e: ut.URITemplateParseError => - Promise[GistCommentOrError].>apply( + Promise[GistCommentOrError] .> apply( req.RequestError(where message' = e.message)) end @@ -175,10 +192,15 @@ primitive UpdateGistComment body: String, creds: req.Credentials): Promise[GistCommentOrError] => + """ + Updates a gist comment at the given API URL. + """ let p = Promise[GistCommentOrError] - let r = req.ResultReceiver[GistComment](creds, - p, - GistCommentJsonConverter) + let r = + req.ResultReceiver[GistComment]( + creds, + p, + GistCommentJSONConverter) let json = JSONObject.update("body", body).print() req.JSONRequester.patch(creds, url, consume json, r) @@ -196,39 +218,48 @@ primitive DeleteGistComment "https://api.github.com/gists{/gist_id}/comments{/comment_id}") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("gist_id", gist_id) - .>set("comment_id", comment_id.string()) + .> set("gist_id", gist_id) + .> set("comment_id", comment_id.string()) let u: String val = tpl.expand(vars) by_url(u, creds) | let e: ut.URITemplateParseError => - Promise[req.DeletedOrError].>apply( + Promise[req.DeletedOrError] .> apply( req.RequestError(where message' = e.message)) end fun by_url(url: String, creds: req.Credentials): Promise[req.DeletedOrError] => + """ + Deletes a gist comment at the given API URL. + """ let p = Promise[req.DeletedOrError] let r = req.DeletedResultReceiver(p) req.NoContentRequester.delete(creds, url, r) p -primitive GistCommentJsonConverter is req.JSONConverter[GistComment] +primitive GistCommentJSONConverter is req.JSONConverter[GistComment] """ Converts a JSON object from the gist comments API into a GistComment. """ fun apply(json: JSONNav, creds: req.Credentials): GistComment ? => + """ + Converts a JSON object into a GistComment. + """ let id = json("id").as_i64()? let node_id = json("node_id").as_string()? let url = json("url").as_string()? let body = json("body").as_string()? - let user = try UserJsonConverter(json("user"), creds)? else None end - let author_association = json("author_association").as_string()? + let user = + try UserJSONConverter(json("user"), creds)? else None end + let author_association = + json("author_association").as_string()? let created_at = json("created_at").as_string()? let updated_at = json("updated_at").as_string()? - GistComment(creds, + GistComment( + creds, id, node_id, url, diff --git a/github_rest_api/gist_commit.pony b/github_rest_api/gist_commit.pony index 7a220a3..c542e1c 100644 --- a/github_rest_api/gist_commit.pony +++ b/github_rest_api/gist_commit.pony @@ -14,12 +14,15 @@ class val GistChangeStatus deletions = deletions' total = total' -primitive GistChangeStatusJsonConverter is req.JSONConverter[GistChangeStatus] +primitive GistChangeStatusJSONConverter is req.JSONConverter[GistChangeStatus] """ Converts a JSON object representing a gist commit's change_status into a GistChangeStatus. """ fun apply(json: JSONNav, creds: req.Credentials): GistChangeStatus ? => + """ + Converts a JSON object into a GistChangeStatus. + """ let additions = json("additions").as_i64()? let deletions = json("deletions").as_i64()? let total = json("total").as_i64()? @@ -52,19 +55,23 @@ class val GistCommit change_status = change_status' user = user' -primitive GistCommitJsonConverter is req.JSONConverter[GistCommit] +primitive GistCommitJSONConverter is req.JSONConverter[GistCommit] """ Converts a JSON object from the gist commits endpoint into a GistCommit. """ fun apply(json: JSONNav, creds: req.Credentials): GistCommit ? => + """ + Converts a JSON object into a GistCommit. + """ let version = json("version").as_string()? let url = json("url").as_string()? let committed_at = json("committed_at").as_string()? let change_status = - GistChangeStatusJsonConverter(json("change_status"), creds)? - let user = try UserJsonConverter(json("user"), creds)? else None end + GistChangeStatusJSONConverter(json("change_status"), creds)? + let user = try UserJSONConverter(json("user"), creds)? else None end - GistCommit(creds, + GistCommit( + creds, version, url, committed_at, diff --git a/github_rest_api/gist_file.pony b/github_rest_api/gist_file.pony index d40e33d..efce83b 100644 --- a/github_rest_api/gist_file.pony +++ b/github_rest_api/gist_file.pony @@ -37,24 +37,30 @@ class val GistFile encoding = encoding' truncated = truncated' -primitive GistFileJsonConverter is req.JSONConverter[GistFile] +primitive GistFileJSONConverter is req.JSONConverter[GistFile] """ Converts a JSON object representing a single gist file into a GistFile. Optional fields that may be absent in list responses are extracted with try/else None. """ fun apply(json: JSONNav, creds: req.Credentials): GistFile ? => + """ + Converts a JSON object into a GistFile. + """ let filename = json("filename").as_string()? let content_type = json("type").as_string()? let language = JSONNavUtil.string_or_none(json("language"))? let raw_url = json("raw_url").as_string()? let size = json("size").as_i64()? - let content = try JSONNavUtil.string_or_none(json("content"))? else None end + let content = + try JSONNavUtil.string_or_none(json("content"))? else None end let encoding = try JSONNavUtil.string_or_none(json("encoding"))? else None end - let truncated = try json("truncated").as_bool()? else None end + let truncated = + try json("truncated").as_bool()? else None end - GistFile(filename, + GistFile( + filename, content_type, language, raw_url, diff --git a/github_rest_api/git_commit.pony b/github_rest_api/git_commit.pony index 827dc5c..62fc999 100644 --- a/github_rest_api/git_commit.pony +++ b/github_rest_api/git_commit.pony @@ -25,13 +25,18 @@ class val GitCommit message = message' url = url' -primitive GitCommitJsonConverter is req.JSONConverter[GitCommit] +primitive GitCommitJSONConverter is req.JSONConverter[GitCommit] """ Converts a JSON object into a GitCommit. """ fun apply(json: JSONNav, creds: req.Credentials): GitCommit ? => - let author = GitPersonJsonConverter(json("author"), creds)? - let committer = GitPersonJsonConverter(json("committer"), creds)? + """ + Parses the JSON representation of a git commit. + """ + let author = + GitPersonJSONConverter(json("author"), creds)? + let committer = + GitPersonJSONConverter(json("committer"), creds)? let message = json("message").as_string()? let url = json("url").as_string()? diff --git a/github_rest_api/git_person.pony b/github_rest_api/git_person.pony index 1830aec..7c98d4f 100644 --- a/github_rest_api/git_person.pony +++ b/github_rest_api/git_person.pony @@ -12,7 +12,7 @@ class val GitPerson name = name' email = email' -primitive GitPersonJsonConverter is req.JSONConverter[GitPerson] +primitive GitPersonJSONConverter is req.JSONConverter[GitPerson] """ Converts a JSON object into a GitPerson. """ diff --git a/github_rest_api/issue.pony b/github_rest_api/issue.pony index 7af1a42..3ed40f7 100644 --- a/github_rest_api/issue.pony +++ b/github_rest_api/issue.pony @@ -42,8 +42,8 @@ type IssueSort is (SortByCreated | SortByUpdated | SortByComments) primitive SortAscending """ - Sort in ascending order (oldest first for time-based sorts, fewest first for - comment count). + Sort in ascending order (oldest first for time-based sorts, + fewest first for comment count). """ fun query_value(): String val => """ @@ -53,8 +53,8 @@ primitive SortAscending primitive SortDescending """ - Sort in descending order (newest first for time-based sorts, most first for - comment count). + Sort in descending order (newest first for time-based sorts, + most first for comment count). """ fun query_value(): String val => """ @@ -69,21 +69,18 @@ type SortDirection is (SortAscending | SortDescending) class val Issue """ - A GitHub issue. Provides convenience methods to create comments and list - existing comments on this issue. The `pull_request` field is present when the - issue is actually a pull request. + A GitHub issue. Provides convenience methods to create comments + and list existing comments on this issue. The `pull_request` field + is present when the issue is actually a pull request. """ let _creds: req.Credentials - let number: I64 let title: String let user: User let labels: Array[Label] val let state: (String | None) let body: (String | None) - let pull_request: (IssuePullRequest | None) - let url: String let respository_url: String let labels_url: String @@ -91,7 +88,8 @@ class val Issue let events_url: String let html_url: String - new val create(creds: req.Credentials, + new val create( + creds: req.Credentials, url': String, respository_url': String, labels_url': String, @@ -121,11 +119,14 @@ class val Issue body = body' pull_request = pull_request' - fun create_comment(comment: String): Promise[IssueCommentOrError] => + fun create_comment( + comment: String): Promise[IssueCommentOrError] + => """ Creates a new comment on this issue. """ - CreateIssueComment.by_url(comments_url, comment, _creds) + CreateIssueComment.by_url( + comments_url, comment, _creds) fun get_comments(): Promise[IssueCommentsOrError] => """ @@ -137,39 +138,53 @@ primitive GetIssue """ Fetches a single issue by owner, repo, and number. """ - fun apply(owner: String, + fun apply( + owner: String, repo: String, number: I64, creds: req.Credentials): Promise[IssueOrError] => match \exhaustive\ ut.URITemplateParse( - "https://api.github.com/repos{/owner}{/repo}/issues{/number}") + "https://api.github.com/repos" + + "{/owner}{/repo}/issues{/number}") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("owner", owner) - .>set("repo", repo) - .>set("number", number.string()) + .> set("owner", owner) + .> set("repo", repo) + .> set("number", number.string()) let u: String val = tpl.expand(vars) by_url(u, creds) | let e: ut.URITemplateParseError => - Promise[IssueOrError].>apply(req.RequestError(where message' = e.message)) + Promise[IssueOrError] .> apply( + req.RequestError( + where message' = e.message)) end - fun by_url(url: String, creds: req.Credentials): Promise[IssueOrError] => + fun by_url( + url: String, + creds: req.Credentials): Promise[IssueOrError] + => + """ + Fetches an issue from a URL. + """ let p = Promise[IssueOrError] - let receiver = req.ResultReceiver[Issue](creds, p, IssueJsonConverter) + let receiver = + req.ResultReceiver[Issue]( + creds, p, IssueJSONConverter) req.JSONRequester.get(creds, url, receiver) p primitive GetRepositoryIssues """ - Lists issues in a repository as a paginated list, optionally filtered by - labels and state. Results can be sorted by creation time, update time, or - comment count, and ordered ascending or descending. The per_page parameter - controls page size (1-100, GitHub defaults to 30). + Lists issues in a repository as a paginated list, optionally + filtered by labels and state. Results can be sorted by creation + time, update time, or comment count, and ordered ascending or + descending. The per_page parameter controls page size (1-100, + GitHub defaults to 30). """ - fun apply(owner: String, + fun apply( + owner: String, repo: String, creds: req.Credentials, labels: String = "", @@ -177,82 +192,116 @@ primitive GetRepositoryIssues sort: IssueSort = SortByCreated, direction: SortDirection = SortDescending, since: String = "", - per_page: (I64 | None) = None): Promise[(PaginatedList[Issue] | req.RequestError)] + per_page: (I64 | None) = None + ): Promise[(PaginatedList[Issue] | req.RequestError)] => match \exhaustive\ ut.URITemplateParse( - "https://api.github.com/repos{/owner}{/repo}/issues") + "https://api.github.com/repos" + + "{/owner}{/repo}/issues") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("owner", owner) - .>set("repo", repo) + .> set("owner", owner) + .> set("repo", repo) let u: String val = tpl.expand(vars) - let params = recover val - let p = Array[(String, String)] - p.push(("state", state)) - p.push(("sort", sort.query_value())) - p.push(("direction", direction.query_value())) - if labels.size() > 0 then - p.push(("labels", labels)) - end - if since.size() > 0 then - p.push(("since", since)) + let params = + recover val + let p = Array[(String, String)] + p.push(("state", state)) + p.push(("sort", sort.query_value())) + p.push(( + "direction", direction.query_value())) + if labels.size() > 0 then + p.push(("labels", labels)) + end + if since.size() > 0 then + p.push(("since", since)) + end + match per_page + | let n: I64 => + p.push(("per_page", n.string())) + end + p end - match per_page - | let n: I64 => p.push(("per_page", n.string())) - end - p - end - by_url(u + req.QueryParams(params), creds) + by_url( + u + req.QueryParams(params), creds) | let e: ut.URITemplateParseError => - Promise[(PaginatedList[Issue] | req.RequestError)].>apply( - req.RequestError(where message' = e.message)) + Promise[ + (PaginatedList[Issue] | req.RequestError) + ] .> apply( + req.RequestError( + where message' = e.message)) end - fun by_url(url: String, - creds: req.Credentials): Promise[(PaginatedList[Issue] | req.RequestError)] + fun by_url( + url: String, + creds: req.Credentials + ): Promise[(PaginatedList[Issue] | req.RequestError)] => - let ic = IssueJsonConverter - let plc = PaginatedListJsonConverter[Issue](creds, ic) - let p = Promise[(PaginatedList[Issue] | req.RequestError)] - let r = PaginatedResultReceiver[Issue](creds, p, plc) + """ + Fetches paginated issues from a URL. + """ + let ic = IssueJSONConverter + let plc = + PaginatedListJSONConverter[Issue](creds, ic) + let p = + Promise[ + (PaginatedList[Issue] | req.RequestError)] + let r = + PaginatedResultReceiver[Issue](creds, p, plc) - LinkedJsonRequester(creds, url, r) + LinkedJSONRequester(creds, url, r) p - -primitive IssueJsonConverter is req.JSONConverter[Issue] +primitive IssueJSONConverter is req.JSONConverter[Issue] """ Converts a JSON object from the issues API into an Issue. """ - fun apply(json: JSONNav, creds: req.Credentials): Issue ? => + fun apply( + json: JSONNav, + creds: req.Credentials): Issue ? + => + """ + Builds an Issue from its JSON representation. + """ let url = json("url").as_string()? - let respository_url = json("repository_url").as_string()? - let labels_url = json("labels_url").as_string()? - let comments_url = json("comments_url").as_string()? - let events_url = json("events_url").as_string()? + let respository_url = + json("repository_url").as_string()? + let labels_url = + json("labels_url").as_string()? + let comments_url = + json("comments_url").as_string()? + let events_url = + json("events_url").as_string()? let html_url = json("html_url").as_string()? let number = json("number").as_i64()? let title = json("title").as_string()? - let user = UserJsonConverter(json("user"), creds)? - let state = JSONNavUtil.string_or_none(json("state"))? - let body = JSONNavUtil.string_or_none(json("body"))? + let user = + UserJSONConverter(json("user"), creds)? + let state = + JSONNavUtil.string_or_none(json("state"))? + let body = + JSONNavUtil.string_or_none(json("body"))? let labels = recover trn Array[Label] end for i in json("labels").as_array()?.values() do - let l = LabelJsonConverter(JSONNav(i), creds)? + let l = + LabelJSONConverter(JSONNav(i), creds)? labels.push(l) end let pr_json = json("pull_request") - let pull_request = match pr_json.json() - | let _: JSONValue => - IssuePullRequestJsonConverter(pr_json, creds)? - else - None - end + let pull_request = + match pr_json.json() + | let _: JSONValue => + IssuePullRequestJSONConverter( + pr_json, creds)? + else + None + end - Issue(creds, + Issue( + creds, url, respository_url, labels_url, diff --git a/github_rest_api/issue_comment.pony b/github_rest_api/issue_comment.pony index 475f1b4..60ddbdd 100644 --- a/github_rest_api/issue_comment.pony +++ b/github_rest_api/issue_comment.pony @@ -5,7 +5,9 @@ use ut = "uri/template" type IssueCommentOrError is (IssueComment | req.RequestError) type IssueComments is Array[IssueComment] val -type IssueCommentsOrError is (IssueComments | req.RequestError) + +type IssueCommentsOrError is + (IssueComments | req.RequestError) class val IssueComment """ @@ -17,7 +19,8 @@ class val IssueComment let html_url: String let issue_url: String - new val create(creds: req.Credentials, + new val create( + creds: req.Credentials, body': String, url': String, html_url': String, @@ -33,7 +36,8 @@ primitive CreateIssueComment """ Creates a new comment on an issue. """ - fun apply(owner: String, + fun apply( + owner: String, repo: String, number: I64, comment: String, @@ -45,28 +49,37 @@ primitive CreateIssueComment | let u': String => by_url(u', comment, creds) | let e: ut.URITemplateParseError => - Promise[IssueCommentOrError].>apply( - req.RequestError(where message' = e.message)) + Promise[IssueCommentOrError] .> apply( + req.RequestError( + where message' = e.message)) end - fun by_url(url: String, + fun by_url( + url: String, comment: String, creds: req.Credentials): Promise[IssueCommentOrError] => + """ + Creates a comment at the given URL. + """ let p = Promise[IssueCommentOrError] - let r = req.ResultReceiver[IssueComment](creds, - p, - IssueCommentJsonConverter) + let r = + req.ResultReceiver[IssueComment]( + creds, + p, + IssueCommentJSONConverter) let json = JSONObject.update("body", comment).print() - req.JSONRequester.post(creds, url, consume json, r) + req.JSONRequester.post( + creds, url, consume json, r) p primitive GetIssueComments """ Fetches all comments on an issue. """ - fun apply(owner: String, + fun apply( + owner: String, repo: String, number: I64, creds: req.Credentials): Promise[IssueCommentsOrError] @@ -77,46 +90,65 @@ primitive GetIssueComments | let u': String => by_url(u', creds) | let e: ut.URITemplateParseError => - Promise[IssueCommentsOrError].>apply( - req.RequestError(where message' = e.message)) + Promise[IssueCommentsOrError] .> apply( + req.RequestError( + where message' = e.message)) end - fun by_url(url: String, creds: req.Credentials): Promise[IssueCommentsOrError] => + fun by_url( + url: String, + creds: req.Credentials + ): Promise[IssueCommentsOrError] + => + """ + Fetches issue comments from a URL. + """ let p = Promise[IssueCommentsOrError] - let r = req.ResultReceiver[IssueComments](creds, - p, - IssueCommentsJsonConverter) + let r = + req.ResultReceiver[IssueComments]( + creds, + p, + IssueCommentsJSONConverter) req.JSONRequester.get(creds, url, r) p primitive IssueCommentsURL """ - Builds the URL for an issue's comments endpoint from owner, repo, and issue - number. + Builds the URL for an issue's comments endpoint from owner, repo, + and issue number. """ - fun apply(owner: String, repo: String, number: I64) - : (String | ut.URITemplateParseError) + fun apply( + owner: String, + repo: String, + number: I64 + ): (String | ut.URITemplateParseError) => match \exhaustive\ ut.URITemplateParse( - "https://api.github.com/repos{/owner}{/repo}/issues{/number}/comments") + "https://api.github.com/repos" + + "{/owner}{/repo}/issues{/number}/comments") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("owner", owner) - .>set("repo", repo) - .>set("number", number.string()) + .> set("owner", owner) + .> set("repo", repo) + .> set("number", number.string()) tpl.expand(vars) | let e: ut.URITemplateParseError => e end -primitive IssueCommentJsonConverter is req.JSONConverter[IssueComment] +primitive IssueCommentJSONConverter is + req.JSONConverter[IssueComment] """ Converts a JSON object into an IssueComment. """ - fun apply(json: JSONNav, + fun apply( + json: JSONNav, creds: req.Credentials): IssueComment ? => + """ + Builds an IssueComment from its JSON representation. + """ let body = json("body").as_string()? let url = json("url").as_string()? let html_url = json("html_url").as_string()? @@ -124,17 +156,24 @@ primitive IssueCommentJsonConverter is req.JSONConverter[IssueComment] IssueComment(creds, body, url, html_url, issue_url) -primitive IssueCommentsJsonConverter is req.JSONConverter[Array[IssueComment] val] +primitive IssueCommentsJSONConverter is + req.JSONConverter[Array[IssueComment] val] """ - Converts a JSON array of issue comment objects into an Array of IssueComment. + Converts a JSON array of issue comment objects into an Array + of IssueComment. """ - fun apply(json: JSONNav, + fun apply( + json: JSONNav, creds: req.Credentials): Array[IssueComment] val ? => + """ + Builds an IssueComment array from JSON. + """ let comments = recover trn Array[IssueComment] end for i in json.as_array()?.values() do - let comment = IssueCommentJsonConverter(JSONNav(i), creds)? + let comment = + IssueCommentJSONConverter(JSONNav(i), creds)? comments.push(comment) end diff --git a/github_rest_api/issue_pull_request.pony b/github_rest_api/issue_pull_request.pony index fffa9ae..41fe243 100644 --- a/github_rest_api/issue_pull_request.pony +++ b/github_rest_api/issue_pull_request.pony @@ -16,7 +16,8 @@ class val IssuePullRequest let patch_url: String let merged_at: (String | None) - new val create(url': String, + new val create( + url': String, html_url': String, diff_url': String, patch_url': String, @@ -28,15 +29,24 @@ class val IssuePullRequest patch_url = patch_url' merged_at = merged_at' -primitive IssuePullRequestJsonConverter is req.JSONConverter[IssuePullRequest] +primitive IssuePullRequestJSONConverter is + req.JSONConverter[IssuePullRequest] """ Converts a JSON object into an IssuePullRequest. """ - fun apply(json: JSONNav, creds: req.Credentials): IssuePullRequest ? => + fun apply( + json: JSONNav, + creds: req.Credentials): IssuePullRequest ? + => + """ + Builds an IssuePullRequest from its JSON representation. + """ let url = json("url").as_string()? let html_url = json("html_url").as_string()? let diff_url = json("diff_url").as_string()? let patch_url = json("patch_url").as_string()? - let merged_at = JSONNavUtil.string_or_none(json("merged_at"))? + let merged_at = + JSONNavUtil.string_or_none(json("merged_at"))? - IssuePullRequest(url, html_url, diff_url, patch_url, merged_at) + IssuePullRequest( + url, html_url, diff_url, patch_url, merged_at) diff --git a/github_rest_api/label.pony b/github_rest_api/label.pony index 5dd9310..1471bac 100644 --- a/github_rest_api/label.pony +++ b/github_rest_api/label.pony @@ -18,7 +18,8 @@ class val Label let default: Bool let description: (String | None) - new val create(creds: req.Credentials, + new val create( + creds: req.Credentials, id': I64, node_id': String, url': String, @@ -40,96 +41,123 @@ primitive CreateLabel """ Creates a new label on a repository. """ - fun apply(owner: String, + fun apply( + owner: String, repo: String, name: String, creds: req.Credentials, color: (String | None) = None, - description: (String | None) = None): Promise[LabelOrError] + description: (String | None) = None + ): Promise[LabelOrError] => match \exhaustive\ ut.URITemplateParse( - "https://api.github.com/repos{/owner}{/repo}/labels") + "https://api.github.com/repos" + + "{/owner}{/repo}/labels") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("owner", owner) - .>set("repo", repo) + .> set("owner", owner) + .> set("repo", repo) let u: String val = tpl.expand(vars) by_url(u, name, creds, color, description) | let e: ut.URITemplateParseError => - Promise[LabelOrError].>apply( - req.RequestError(where message' = e.message)) + Promise[LabelOrError] .> apply( + req.RequestError( + where message' = e.message)) end - fun by_url(url: String, + fun by_url( + url: String, name: String, creds: req.Credentials, color: (String | None) = None, - description: (String | None) = None): Promise[LabelOrError] + description: (String | None) = None + ): Promise[LabelOrError] => + """ + Creates a label at the given URL. + """ let p = Promise[LabelOrError] - let r = req.ResultReceiver[Label](creds, - p, - LabelJsonConverter) + let r = + req.ResultReceiver[Label]( + creds, + p, + LabelJSONConverter) var obj = JSONObject.update("name", name) match color | let c: String => obj = obj.update("color", c) end match description - | let d: String => obj = obj.update("description", d) + | let d: String => + obj = obj.update("description", d) end let json = obj.print() - req.JSONRequester.post(creds, url, consume json, r) + req.JSONRequester.post( + creds, url, consume json, r) p primitive DeleteLabel """ Deletes a label from a repository. """ - fun apply(owner: String, + fun apply( + owner: String, repo: String, name: String, creds: req.Credentials): Promise[req.DeletedOrError] => match \exhaustive\ ut.URITemplateParse( - "https://api.github.com/repos{/owner}{/repo}/labels{/name}") + "https://api.github.com/repos" + + "{/owner}{/repo}/labels{/name}") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("owner", owner) - .>set("repo", repo) - .>set("name", name) + .> set("owner", owner) + .> set("repo", repo) + .> set("name", name) let u: String val = tpl.expand(vars) by_url(u, name, creds) | let e: ut.URITemplateParseError => - Promise[req.DeletedOrError].>apply( - req.RequestError(where message' = e.message)) + Promise[req.DeletedOrError] .> apply( + req.RequestError( + where message' = e.message)) end - - fun by_url(url: String, + fun by_url( + url: String, name: String, creds: req.Credentials): Promise[req.DeletedOrError] => + """ + Deletes a label at the given URL. + """ let p = Promise[req.DeletedOrError] let r = req.DeletedResultReceiver(p) req.NoContentRequester.delete(creds, url, r) p -primitive LabelJsonConverter is req.JSONConverter[Label] +primitive LabelJSONConverter is req.JSONConverter[Label] """ Converts a JSON object into a Label. """ - fun apply(json: JSONNav, creds: req.Credentials): Label ? => + fun apply( + json: JSONNav, + creds: req.Credentials): Label ? + => + """ + Builds a Label from its JSON representation. + """ let id = json("id").as_i64()? let node_id = json("node_id").as_string()? let url = json("url").as_string()? let name = json("name").as_string()? let color = json("color").as_string()? let default = json("default").as_bool()? - let description = JSONNavUtil.string_or_none(json("description"))? + let description = + JSONNavUtil.string_or_none(json("description"))? - Label(creds, + Label( + creds, id, node_id, url, diff --git a/github_rest_api/license.pony b/github_rest_api/license.pony index cc925ae..a121e0b 100644 --- a/github_rest_api/license.pony +++ b/github_rest_api/license.pony @@ -27,18 +27,22 @@ class val License spdx_id = spdx_id' url = url' -primitive LicenseJsonConverter is req.JSONConverter[License] +primitive LicenseJSONConverter is req.JSONConverter[License] """ Converts a JSON object into a License. """ fun apply(json: JSONNav, creds: req.Credentials): License ? => + """ + Parses the JSON representation of a license. + """ let node_id = json("node_id").as_string()? let name = json("name").as_string()? let key = json("key").as_string()? let spdx_id = json("spdx_id").as_string()? let url = json("url").as_string()? - License(creds, + License( + creds, node_id, name, key, diff --git a/github_rest_api/linked_result_receiver.pony b/github_rest_api/linked_result_receiver.pony new file mode 100644 index 0000000..d179f3a --- /dev/null +++ b/github_rest_api/linked_result_receiver.pony @@ -0,0 +1,17 @@ +use "json" + +interface tag LinkedResultReceiver + """ + Receives the result of an HTTP GET request that returns JSON + along with a Link header. Used by both paginated list and search + result requesters. + """ + be success(json: JSONNav, link_header: String) + """ + Called when the request succeeds with parsed JSON. + """ + + be failure(status: U16, response_body: String, message: String) + """ + Called when the request fails. + """ diff --git a/github_rest_api/paginated_list.pony b/github_rest_api/paginated_list.pony index 24105c7..6bab1fc 100644 --- a/github_rest_api/paginated_list.pony +++ b/github_rest_api/paginated_list.pony @@ -6,42 +6,40 @@ use req = "request" use ssl = "ssl/net" use uri = "uri" -interface tag LinkedResultReceiver - """ - Receives the result of an HTTP GET request that returns JSON along with a - Link header. Used by both paginated list and search result requesters. - """ - be success(json: JSONNav, link_header: String) - be failure(status: U16, response_body: String, message: String) - class val PaginatedList[A: Any val] """ - A page of results from a paginated GitHub API endpoint. Use `prev_page()` - and `next_page()` to navigate between pages; each returns a Promise for the - adjacent page, or None if no such page exists. + A page of results from a paginated GitHub API endpoint. Use + `prev_page()` and `next_page()` to navigate between pages; each + returns a Promise for the adjacent page, or None if no such page + exists. """ let _creds: req.Credentials - let _converter: PaginatedListJsonConverter[A] + let _converter: PaginatedListJSONConverter[A] let _prev_link: (String | None) let _next_link: (String | None) - let results: Array[A] val - new val _from_array(creds: req.Credentials, + new val _from_array( + creds: req.Credentials, converter: req.JSONConverter[A], results': Array[A] val, prev_link: (String | None) = None, next_link: (String | None) = None) => _creds = creds - _converter = PaginatedListJsonConverter[A](_creds, converter) + _converter = + PaginatedListJSONConverter[A](_creds, converter) results = results' _prev_link = prev_link _next_link = next_link - fun prev_page(): (Promise[(PaginatedList[A] | req.RequestError)] | None) => + fun prev_page() + : (Promise[(PaginatedList[A] | req.RequestError)] + | None) + => """ - Fetches the previous page, or returns None if on the first page. + Fetches the previous page, or returns None if on the first + page. """ match \exhaustive\ _prev_link | let prev: String => @@ -50,7 +48,10 @@ class val PaginatedList[A: Any val] None end - fun next_page(): (Promise[(PaginatedList[A] | req.RequestError)] | None) => + fun next_page() + : (Promise[(PaginatedList[A] | req.RequestError)] + | None) + => """ Fetches the next page, or returns None if on the last page. """ @@ -61,31 +62,42 @@ class val PaginatedList[A: Any val] None end - fun _retrieve_link(link: String): - Promise[(PaginatedList[A] | req.RequestError)] + fun _retrieve_link( + link: String) + : Promise[(PaginatedList[A] | req.RequestError)] => - let p = Promise[(PaginatedList[A] | req.RequestError)] - let r = PaginatedResultReceiver[A](_creds, p, _converter) - LinkedJsonRequester(_creds, link, r) + let p = + Promise[(PaginatedList[A] | req.RequestError)] + let r = + PaginatedResultReceiver[A](_creds, p, _converter) + LinkedJSONRequester(_creds, link, r) p -class val PaginatedListJsonConverter[A: Any val] +class val PaginatedListJSONConverter[A: Any val] """ - Converts a JSON array response with Link header pagination into a - PaginatedList. Delegates individual item conversion to the wrapped - JSONConverter. + Converts a JSON array response with Link header pagination into + a PaginatedList. Delegates individual item conversion to the + wrapped JSONConverter. """ let _creds: req.Credentials let _converter: req.JSONConverter[A] - new val create(creds: req.Credentials, converter: req.JSONConverter[A]) => + new val create( + creds: req.Credentials, + converter: req.JSONConverter[A]) + => _creds = creds _converter = converter - fun apply(json: JSONNav, + fun apply( + json: JSONNav, link_header: String, - creds: req.Credentials): PaginatedList[A] ? + creds: req.Credentials) + : PaginatedList[A] ? => + """ + Converts JSON and Link header into a PaginatedList. + """ let entries = recover trn Array[A] end for i in json.as_array()?.values() do @@ -93,9 +105,11 @@ class val PaginatedListJsonConverter[A: Any val] entries.push(e) end - (let prev, let next) = _ExtractPaginationLinks(link_header) + (let prev, let next) = + _ExtractPaginationLinks(link_header) - PaginatedList[A]._from_array(_creds, + PaginatedList[A]._from_array( + _creds, _converter, consume entries, prev, @@ -103,16 +117,17 @@ class val PaginatedListJsonConverter[A: Any val] actor PaginatedResultReceiver[A: Any val] """ - Receives the HTTP response for a paginated request and fulfills the - associated Promise with a PaginatedList or RequestError. + Receives the HTTP response for a paginated request and fulfills + the associated Promise with a PaginatedList or RequestError. """ let _creds: req.Credentials let _p: Promise[(PaginatedList[A] | req.RequestError)] - let _converter: PaginatedListJsonConverter[A] + let _converter: PaginatedListJSONConverter[A] - new create(creds: req.Credentials, + new create( + creds: req.Credentials, p: Promise[(PaginatedList[A] | req.RequestError)], - c: PaginatedListJsonConverter[A]) + c: PaginatedListJSONConverter[A]) => _creds = creds _p = p @@ -122,24 +137,34 @@ actor PaginatedResultReceiver[A: Any val] try _p(_converter(json, link_header, _creds)?) else - let m = recover val - "Unable to convert json for " + req.JSONTypeString(json) - end + let m = + recover val + "Unable to convert json for " + + req.JSONTypeString(json) + end _p(req.RequestError(where message' = m)) end - be failure(status: U16, response_body: String, message: String) => + be failure( + status: U16, + response_body: String, + message: String) + => _p(req.RequestError(status, response_body, message)) -actor LinkedJsonRequester is courier.HTTPClientConnectionActor +actor LinkedJSONRequester + is courier.HTTPClientConnectionActor """ - Issues an HTTP GET request and delivers the JSON response along with the - Link header to a LinkedResultReceiver. Used by both paginated list and search - result endpoints. Follows 301/307 redirects automatically. + Issues an HTTP GET request and delivers the JSON response along + with the Link header to a LinkedResultReceiver. Used by both + paginated list and search result endpoints. Follows 301/307 + redirects automatically. """ - var _http: courier.HTTPClientConnection = courier.HTTPClientConnection.none() - var _collector: courier.ResponseCollector = courier.ResponseCollector + var _http: courier.HTTPClientConnection = + courier.HTTPClientConnection.none() + var _collector: courier.ResponseCollector = + courier.ResponseCollector let _creds: req.Credentials let _receiver: LinkedResultReceiver var _request_path: String = "" @@ -147,38 +172,48 @@ actor LinkedJsonRequester is courier.HTTPClientConnectionActor var _status: U16 = 0 var _link_header: String = "" - new create(creds: req.Credentials, + new create( + creds: req.Credentials, url: String, receiver: LinkedResultReceiver) => """ - Issues an HTTP GET request expecting a 200 response with JSON body and - Link header for pagination. + Issues an HTTP GET request expecting a 200 response with JSON + body and Link header for pagination. """ _creds = creds _receiver = receiver _connect(url) fun ref _connect(url: String) => - match uri.ParseURI(url) + match \exhaustive\ uri.ParseURI(url) | let parsed: uri.URI val => - match parsed.authority + match \exhaustive\ parsed.authority | let auth: uri.URIAuthority => _request_path = parsed.path match parsed.query - | let q: String => _request_path = _request_path + "?" + q - end - let port = match auth.port - | let p: U16 => p.string() - | None => "443" - end - let ctx = match _creds.ssl_ctx - | let c: ssl.SSLContext val => c - | None => req.SSLContextFactory() + | let q: String => + _request_path = _request_path + "?" + q end + let port = + match \exhaustive\ auth.port + | let p: U16 => p.string() + | None => "443" + end + let ctx = + match \exhaustive\ _creds.ssl_ctx + | let c: ssl.SSLContext val => c + | None => req.SSLContextFactory() + end let config = courier.ClientConnectionConfig - _http = courier.HTTPClientConnection.ssl( - _creds.auth, ctx, auth.host, port, this, config) + _http = + courier.HTTPClientConnection.ssl( + _creds.auth, + ctx, + auth.host, + port, + this, + config) else _fail("Unable to parse URL: " + url) end @@ -186,37 +221,49 @@ actor LinkedJsonRequester is courier.HTTPClientConnectionActor _fail("Unable to parse URL: " + url) end - fun ref _http_client_connection(): courier.HTTPClientConnection => + fun ref _http_client_connection() + : courier.HTTPClientConnection + => _http fun ref on_connected() => + """ + Sends the HTTP GET request when connected. + """ let hdrs = recover trn courier.Headers end - hdrs.set("User-Agent", "Pony GitHub Rest API Client") - hdrs.set("Accept", "application/vnd.github.v3+json") + hdrs.set( + "User-Agent", "Pony GitHub Rest API Client") + hdrs.set( + "Accept", "application/vnd.github.v3+json") match _creds.token | let t: String => (let n, let v) = courier.BearerAuth(t) hdrs.set(n, v) end - let request = courier.HTTPRequest( - courier.GET, - _request_path, - consume hdrs) + let request = + courier.HTTPRequest( + courier.GET, + _request_path, + consume hdrs) _http.send_request(request) fun ref on_response(response: courier.Response val) => + """ + Handles the HTTP response status and headers. + """ _status = response.status - _link_header = match response.headers.get("link") - | let h: String => h - | None => "" - end + _link_header = + match \exhaustive\ response.headers.get("link") + | let h: String => h + | None => "" + end if (_status == 301) or (_status == 307) then match response.headers.get("location") | let loc: String => _redirected = true _http.close() - LinkedJsonRequester(_creds, loc, _receiver) + LinkedJSONRequester(_creds, loc, _receiver) return end end @@ -233,28 +280,42 @@ actor LinkedJsonRequester is courier.HTTPClientConnectionActor try let response = _collector.build()? if _status == 200 then - match \exhaustive\ courier.ResponseJSON(response) + match \exhaustive\ courier.ResponseJSON( + response) | let json: JSONValue => - _receiver.success(JSONNav(json), _link_header) + _receiver.success( + JSONNav(json), _link_header) | let _: JSONParseError => - _receiver.failure(_status, "", "Failed to parse response") + _receiver.failure( + _status, "", "Failed to parse response") end else - let body_str = String.from_array(response.body) - _receiver.failure(_status, consume body_str, "") + let body_str = + String.from_array(response.body) + _receiver.failure( + _status, consume body_str, "") end else - _receiver.failure(0, "", "Failed to build response") + _receiver.failure( + 0, "", "Failed to build response") end - fun ref on_connection_failure(reason: courier.ConnectionFailureReason) => - let msg = match \exhaustive\ reason - | courier.ConnectionFailedDNS => "DNS resolution failed" - | courier.ConnectionFailedTCP => "Unable to connect" - | courier.ConnectionFailedSSL => "SSL handshake failed" - | courier.ConnectionFailedTimeout => "Connection timed out" - | courier.ConnectionFailedTimerError => "Connect timer failed" - end + fun ref on_connection_failure( + reason: courier.ConnectionFailureReason) + => + let msg = + match \exhaustive\ reason + | courier.ConnectionFailedDNS => + "DNS resolution failed" + | courier.ConnectionFailedTCP => + "Unable to connect" + | courier.ConnectionFailedSSL => + "SSL handshake failed" + | courier.ConnectionFailedTimeout => + "Connection timed out" + | courier.ConnectionFailedTimerError => + "Connect timer failed" + end _receiver.failure(0, "", consume msg) fun ref on_parse_error(err: courier.ParseError) => diff --git a/github_rest_api/pull_request.pony b/github_rest_api/pull_request.pony index c03c23d..60a86d3 100644 --- a/github_rest_api/pull_request.pony +++ b/github_rest_api/pull_request.pony @@ -11,7 +11,6 @@ class val PullRequest changed in this pull request. """ let _creds: req.Credentials - let number: I64 let title: String let body: (String | None) @@ -23,7 +22,8 @@ class val PullRequest let files_url: String let comments_url: String - new val create(creds: req.Credentials, + new val create( + creds: req.Credentials, number': I64, title': String, body': (String | None), @@ -56,57 +56,82 @@ primitive GetPullRequest """ Fetches a single pull request by owner, repo, and number. """ - fun apply(owner: String, + fun apply( + owner: String, repo: String, number: I64, creds: req.Credentials): Promise[PullRequestOrError] => match \exhaustive\ ut.URITemplateParse( - "https://api.github.com/repos{/owner}{/repo}/pulls{/number}") + "https://api.github.com/repos" + + "{/owner}{/repo}/pulls{/number}") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("owner", owner) - .>set("repo", repo) - .>set("number", number.string()) + .> set("owner", owner) + .> set("repo", repo) + .> set("number", number.string()) let u: String val = tpl.expand(vars) by_url(u, creds) | let e: ut.URITemplateParseError => - Promise[PullRequestOrError].>apply( - req.RequestError(where message' = e.message)) + Promise[PullRequestOrError] .> apply( + req.RequestError( + where message' = e.message)) end - fun by_url(url: String, creds: req.Credentials): Promise[PullRequestOrError] => + fun by_url( + url: String, + creds: req.Credentials + ): Promise[PullRequestOrError] + => + """ + Fetches a pull request from a URL. + """ let p = Promise[PullRequestOrError] - let r = req.ResultReceiver[PullRequest](creds, - p, - PullRequestJsonConverter) + let r = + req.ResultReceiver[PullRequest]( + creds, + p, + PullRequestJSONConverter) req.JSONRequester.get(creds, url, r) p -primitive PullRequestJsonConverter is req.JSONConverter[PullRequest] +primitive PullRequestJSONConverter is + req.JSONConverter[PullRequest] """ Converts a JSON object from the pulls API into a PullRequest. """ - fun apply(json: JSONNav, creds: req.Credentials): PullRequest ? => + fun apply( + json: JSONNav, + creds: req.Credentials): PullRequest ? + => + """ + Builds a PullRequest from its JSON representation. + """ let number = json("number").as_i64()? let title = json("title").as_string()? - let body = JSONNavUtil.string_or_none(json("body"))? + let body = + JSONNavUtil.string_or_none(json("body"))? let state = json("state").as_string()? let labels = recover trn Array[Label] end for i in json("labels").as_array()?.values() do - let l = LabelJsonConverter(JSONNav(i), creds)? + let l = + LabelJSONConverter(JSONNav(i), creds)? labels.push(l) end - let base = PullRequestBaseJsonConverter(json("base"), creds)? + let base = + PullRequestBaseJSONConverter( + json("base"), creds)? let url = json("url").as_string()? let html_url = json("html_url").as_string()? - let comments_url = json("comments_url").as_string()? + let comments_url = + json("comments_url").as_string()? - PullRequest(creds, + PullRequest( + creds, number, title, body, diff --git a/github_rest_api/pull_request_base.pony b/github_rest_api/pull_request_base.pony index 73851db..ee0d028 100644 --- a/github_rest_api/pull_request_base.pony +++ b/github_rest_api/pull_request_base.pony @@ -13,7 +13,8 @@ class val PullRequestBase let user: User let repo: Repository - new val create(creds: req.Credentials, + new val create( + creds: req.Credentials, label': String, reference': String, sha': String, @@ -27,15 +28,25 @@ class val PullRequestBase user = user' repo = repo' -primitive PullRequestBaseJsonConverter is req.JSONConverter[PullRequestBase] +primitive PullRequestBaseJSONConverter is + req.JSONConverter[PullRequestBase] """ Converts a JSON object into a PullRequestBase. """ - fun apply(json: JSONNav, creds: req.Credentials): PullRequestBase ? => + fun apply( + json: JSONNav, + creds: req.Credentials): PullRequestBase ? + => + """ + Builds a PullRequestBase from its JSON representation. + """ let label = json("label").as_string()? let reference = json("ref").as_string()? let sha = json("sha").as_string()? - let user = UserJsonConverter(json("user"), creds)? - let repo = RepositoryJsonConverter(json("repo"), creds)? + let user = + UserJSONConverter(json("user"), creds)? + let repo = + RepositoryJSONConverter(json("repo"), creds)? - PullRequestBase(creds, label, reference, sha, user, repo) + PullRequestBase( + creds, label, reference, sha, user, repo) diff --git a/github_rest_api/pull_request_file.pony b/github_rest_api/pull_request_file.pony index 8b8c4fb..cadfa5f 100644 --- a/github_rest_api/pull_request_file.pony +++ b/github_rest_api/pull_request_file.pony @@ -4,7 +4,9 @@ use req = "request" use ut = "uri/template" type PullRequestFiles is Array[PullRequestFile] val -type PullRequestFilesOrError is (PullRequestFiles | req.RequestError) + +type PullRequestFilesOrError is + (PullRequestFiles | req.RequestError) class val PullRequestFile """ @@ -21,45 +23,59 @@ primitive GetPullRequestFiles """ Fetches the list of files changed in a pull request. """ - fun apply(owner: String, + fun apply( + owner: String, repo: String, number: I64, creds: req.Credentials): Promise[PullRequestFilesOrError] => match \exhaustive\ ut.URITemplateParse( - "https://api.github.com/repos{/owner}{/repo}/pulls{/number}/files") + "https://api.github.com/repos" + + "{/owner}{/repo}/pulls{/number}/files") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("owner", owner) - .>set("repo", repo) - .>set("number", number.string()) + .> set("owner", owner) + .> set("repo", repo) + .> set("number", number.string()) let u: String val = tpl.expand(vars) by_url(u, creds) | let e: ut.URITemplateParseError => - Promise[PullRequestFilesOrError].>apply( - req.RequestError(where message' = e.message)) + Promise[PullRequestFilesOrError] .> apply( + req.RequestError( + where message' = e.message)) end - fun by_url(url: String, - creds: req.Credentials): Promise[PullRequestFilesOrError] + fun by_url( + url: String, + creds: req.Credentials + ): Promise[PullRequestFilesOrError] => + """ + Fetches pull request files from a URL. + """ let p = Promise[PullRequestFilesOrError] - let r = req.ResultReceiver[PullRequestFiles](creds, - p, - PullRequestFilesJsonConverter) + let r = + req.ResultReceiver[PullRequestFiles]( + creds, + p, + PullRequestFilesJSONConverter) req.JSONRequester.get(creds, url, r) p -primitive PullRequestFilesJsonConverter is +primitive PullRequestFilesJSONConverter is req.JSONConverter[Array[PullRequestFile] val] """ Converts a JSON array of pull request file objects into an Array of PullRequestFile. """ - fun apply(json: JSONNav, + fun apply( + json: JSONNav, creds: req.Credentials): Array[PullRequestFile] val ? => + """ + Builds a PullRequestFile array from JSON. + """ let files = recover trn Array[PullRequestFile] end for i in json.as_array()?.values() do diff --git a/github_rest_api/release.pony b/github_rest_api/release.pony index f31dc7c..22ae33d 100644 --- a/github_rest_api/release.pony +++ b/github_rest_api/release.pony @@ -7,11 +7,10 @@ type ReleaseOrError is (Release | req.RequestError) class val Release """ - A GitHub release, containing its tag, target commit, release notes body, - draft/prerelease status, and associated assets. + A GitHub release, containing its tag, target commit, release + notes body, draft/prerelease status, and associated assets. """ let _creds: req.Credentials - let id: I64 let node_id: String let author: User @@ -21,11 +20,9 @@ class val Release let body: String let draft: Bool let prerelease: Bool - let created_at: String let published_at: String let assets: Array[Asset] val - let url: String let assets_url: String let upload_url: String @@ -33,7 +30,8 @@ class val Release let tarball_url: String let zipball_url: String - new val create(creds: req.Credentials, + new val create( + creds: req.Credentials, id': I64, node_id': String, author': User, @@ -77,7 +75,8 @@ primitive CreateRelease """ Creates a new release on a repository. """ - fun apply(owner: String, + fun apply( + owner: String, repo: String, tag_name: String, name: String, @@ -85,16 +84,22 @@ primitive CreateRelease creds: req.Credentials, target_commitish: (String | None) = None, draft: Bool = false, - prerelease: Bool = false): Promise[ReleaseOrError] + prerelease: Bool = false) + : Promise[ReleaseOrError] => + """ + Creates a release by owner and repo name. + """ match \exhaustive\ ut.URITemplateParse( - "https://api.github.com/repos{/owner}{/repo}/releases") + "https://api.github.com/repos" + + "{/owner}{/repo}/releases") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("owner", owner) - .>set("repo", repo) + .> set("owner", owner) + .> set("repo", repo) let u: String val = tpl.expand(vars) - by_url(u, + by_url( + u, tag_name, name, body, @@ -103,22 +108,31 @@ primitive CreateRelease draft, prerelease) | let e: ut.URITemplateParseError => - Promise[ReleaseOrError].>apply(req.RequestError(where message' = e.message)) + Promise[ReleaseOrError] .> apply( + req.RequestError( + where message' = e.message)) end - fun by_url(url: String, + fun by_url( + url: String, tag_name: String, name: String, body: String, creds: req.Credentials, target_commitish: (String | None) = None, draft: Bool = false, - prerelease: Bool = false): Promise[ReleaseOrError] + prerelease: Bool = false) + : Promise[ReleaseOrError] => + """ + Creates a release by direct API URL. + """ let p = Promise[ReleaseOrError] - let r = req.ResultReceiver[Release](creds, - p, - ReleaseJsonConverter) + let r = + req.ResultReceiver[Release]( + creds, + p, + ReleaseJSONConverter) var obj = JSONObject .update("tag_name", tag_name) @@ -128,42 +142,62 @@ primitive CreateRelease | let tc: String => obj = obj.update("target_commitish", tc) end - obj = obj.update("draft", draft).update("prerelease", prerelease) + obj = obj + .update("draft", draft) + .update("prerelease", prerelease) let json = obj.print() - req.JSONRequester.post(creds, url, consume json, r) + req.JSONRequester.post( + creds, url, consume json, r) p -primitive ReleaseJsonConverter is req.JSONConverter[Release] +primitive ReleaseJSONConverter + is req.JSONConverter[Release] """ Converts a JSON object from the releases API into a Release. """ - fun apply(json: JSONNav, creds: req.Credentials): Release ? => + fun apply( + json: JSONNav, + creds: req.Credentials) + : Release ? + => + """ + Converts a JSON object into a Release. + """ let id = json("id").as_i64()? let node_id = json("node_id").as_string()? - let author = UserJsonConverter(json("author"), creds)? + let author = + UserJSONConverter(json("author"), creds)? let tag_name = json("tag_name").as_string()? - let target_commitish = json("target_commitish").as_string()? + let target_commitish = + json("target_commitish").as_string()? let name = json("name").as_string()? let body = json("body").as_string()? let draft = json("draft").as_bool()? let prerelease = json("prerelease").as_bool()? let created_at = json("created_at").as_string()? - let published_at = json("published_at").as_string()? + let published_at = + json("published_at").as_string()? let assets = recover trn Array[Asset] end for i in json("assets").as_array()?.values() do - let a = AssetJsonConverter(JSONNav(i), creds)? + let a = + AssetJSONConverter(JSONNav(i), creds)? assets.push(a) end let url = json("url").as_string()? - let assets_url = json("assets_url").as_string()? - let upload_url = json("upload_url").as_string()? + let assets_url = + json("assets_url").as_string()? + let upload_url = + json("upload_url").as_string()? let html_url = json("html_url").as_string()? - let tarball_url = json("tarball_url").as_string()? - let zipball_url = json("zipball_url").as_string()? + let tarball_url = + json("tarball_url").as_string()? + let zipball_url = + json("zipball_url").as_string()? - Release(creds, + Release( + creds, id, node_id, author, diff --git a/github_rest_api/repository.pony b/github_rest_api/repository.pony index 865c93e..cf339b2 100644 --- a/github_rest_api/repository.pony +++ b/github_rest_api/repository.pony @@ -19,15 +19,12 @@ class val Repository let owner: User let private: Bool let fork: Bool - let created_at: String let pushed_at: String let updated_at: String - let homepage: (String | None) let default_branch: String let organization: (User | None) - let size: I64 let forks: I64 let forks_count: I64 @@ -38,19 +35,15 @@ class val Repository let subscribers_count: (I64 | None) let watchers: I64 let watchers_count: I64 - let language: (String | None) let license: (License | None) - let archived: Bool let disabled: Bool - let has_downloads: Bool let has_issues: Bool let has_pages: Bool let has_projects: Bool let has_wiki: Bool - let url: String let html_url: String let archive_url: String @@ -86,7 +79,6 @@ class val Repository let subscription_url: String let tags_url: String let trees_url: String - let clone_url: String let git_url: String let mirror_url: (String | None) @@ -94,7 +86,8 @@ class val Repository let svn_url: String // TODO temp_clone_token: ? | None - new val create(creds: req.Credentials, + new val create( + creds: req.Credentials, id': I64, node_id': String, name': String, @@ -244,9 +237,11 @@ class val Repository ssh_url = ssh_url' svn_url = svn_url' - fun create_label(label_name: String, + fun create_label( + label_name: String, color: (String | None) = None, - label_description: (String | None) = None): Promise[LabelOrError] + label_description: (String | None) = None) + : Promise[LabelOrError] => """ Creates a new label on this repository. @@ -254,21 +249,26 @@ class val Repository match \exhaustive\ ut.URITemplateParse(labels_url) | let tpl: ut.URITemplate => let u: String val = tpl.expand(ut.URITemplateVariables) - CreateLabel.by_url(u, + CreateLabel.by_url( + u, label_name, _creds, color, label_description) | let e: ut.URITemplateParseError => - Promise[LabelOrError].>apply(req.RequestError(where message' = e.message)) + Promise[LabelOrError] .> apply( + req.RequestError( + where message' = e.message)) end - fun create_release(tag_name: String, + fun create_release( + tag_name: String, release_name: String, body: String, target_commitish: (String | None) = None, draft: Bool = false, - prerelease: Bool = false): Promise[ReleaseOrError] + prerelease: Bool = false) + : Promise[ReleaseOrError] => """ Creates a new release on this repository. @@ -276,7 +276,8 @@ class val Repository match \exhaustive\ ut.URITemplateParse(releases_url) | let tpl: ut.URITemplate => let u: String val = tpl.expand(ut.URITemplateVariables) - CreateRelease.by_url(u, + CreateRelease.by_url( + u, tag_name, release_name, body, @@ -285,21 +286,27 @@ class val Repository draft, prerelease) | let e: ut.URITemplateParseError => - Promise[ReleaseOrError].>apply(req.RequestError(where message' = e.message)) + Promise[ReleaseOrError] .> apply( + req.RequestError( + where message' = e.message)) end - fun delete_label(label_name: String): Promise[req.DeletedOrError] => + fun delete_label(label_name: String) + : Promise[req.DeletedOrError] + => """ Deletes a label from this repository. """ match \exhaustive\ ut.URITemplateParse(labels_url) | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("name", label_name) + .> set("name", label_name) let u: String val = tpl.expand(vars) DeleteLabel.by_url(u, label_name, _creds) | let e: ut.URITemplateParseError => - Promise[req.DeletedOrError].>apply(req.RequestError(where message' = e.message)) + Promise[req.DeletedOrError] .> apply( + req.RequestError( + where message' = e.message)) end fun get_commit(sha: String): Promise[CommitOrError] => @@ -309,11 +316,13 @@ class val Repository match \exhaustive\ ut.URITemplateParse(commits_url) | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("sha", sha) + .> set("sha", sha) let u: String val = tpl.expand(vars) GetCommit.by_url(u, _creds) | let e: ut.URITemplateParseError => - Promise[CommitOrError].>apply(req.RequestError(where message' = e.message)) + Promise[CommitOrError] .> apply( + req.RequestError( + where message' = e.message)) end fun get_issue(number: I64): Promise[IssueOrError] => @@ -323,14 +332,17 @@ class val Repository match \exhaustive\ ut.URITemplateParse(issues_url) | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("number", number.string()) + .> set("number", number.string()) let u: String val = tpl.expand(vars) GetIssue.by_url(u, _creds) | let e: ut.URITemplateParseError => - Promise[IssueOrError].>apply(req.RequestError(where message' = e.message)) + Promise[IssueOrError] .> apply( + req.RequestError( + where message' = e.message)) end - fun get_issues(labels: String = "", + fun get_issues( + labels: String = "", state: String = "open", sort: IssueSort = SortByCreated, direction: SortDirection = SortDescending, @@ -339,76 +351,104 @@ class val Repository : Promise[(PaginatedList[Issue] | req.RequestError)] => """ - Lists issues in this repository, optionally filtered by labels and state. - Results can be sorted by creation time, update time, or comment count, and - ordered ascending or descending. The per_page parameter controls page size - (1-100, GitHub defaults to 30). + Lists issues in this repository, optionally filtered by labels + and state. Results can be sorted by creation time, update time, + or comment count, and ordered ascending or descending. The + per_page parameter controls page size (1-100, GitHub defaults + to 30). """ match \exhaustive\ ut.URITemplateParse(issues_url) | let tpl: ut.URITemplate => - let u: String val = tpl.expand(ut.URITemplateVariables) - let params = recover val - let p = Array[(String, String)] - p.push(("state", state)) - p.push(("sort", sort.query_value())) - p.push(("direction", direction.query_value())) - if labels.size() > 0 then - p.push(("labels", labels)) + let u: String val = + tpl.expand(ut.URITemplateVariables) + let params = + recover val + let p = Array[(String, String)] + p.push(("state", state)) + p.push(("sort", sort.query_value())) + p.push(( + "direction", direction.query_value())) + if labels.size() > 0 then + p.push(("labels", labels)) + end + if since.size() > 0 then + p.push(("since", since)) + end + match per_page + | let n: I64 => + p.push(("per_page", n.string())) + end + p end - if since.size() > 0 then - p.push(("since", since)) - end - match per_page - | let n: I64 => p.push(("per_page", n.string())) - end - p - end - GetRepositoryIssues.by_url(u + req.QueryParams(params), _creds) + GetRepositoryIssues.by_url( + u + req.QueryParams(params), _creds) | let e: ut.URITemplateParseError => - Promise[(PaginatedList[Issue] | req.RequestError)].>apply( - req.RequestError(where message' = e.message)) + Promise[(PaginatedList[Issue] | req.RequestError)] + .> apply( + req.RequestError( + where message' = e.message)) end - fun get_pull_request(number: I64): Promise[PullRequestOrError] => + fun get_pull_request(number: I64) + : Promise[PullRequestOrError] + => """ - Fetches a single pull request from this repository by its number. + Fetches a single pull request from this repository by its + number. """ match \exhaustive\ ut.URITemplateParse(pulls_url) | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("number", number.string()) + .> set("number", number.string()) let u: String val = tpl.expand(vars) GetPullRequest.by_url(u, _creds) | let e: ut.URITemplateParseError => - Promise[PullRequestOrError].>apply( - req.RequestError(where message' = e.message)) + Promise[PullRequestOrError] .> apply( + req.RequestError( + where message' = e.message)) end primitive GetRepository """ Fetches a single repository by owner and name. """ - fun apply(owner: String, + fun apply( + owner: String, repo: String, - creds: req.Credentials): Promise[RepositoryOrError] + creds: req.Credentials) + : Promise[RepositoryOrError] => - match \exhaustive\ ut.URITemplateParse("https://api.github.com/repos{/owner}{/repo}") + """ + Fetches a repository by owner and repo name. + """ + match \exhaustive\ ut.URITemplateParse( + "https://api.github.com/repos{/owner}{/repo}") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("owner", owner) - .>set("repo", repo) + .> set("owner", owner) + .> set("repo", repo) let u: String val = tpl.expand(vars) by_url(u, creds) | let e: ut.URITemplateParseError => - Promise[RepositoryOrError].>apply( - req.RequestError(where message' = e.message)) + Promise[RepositoryOrError] .> apply( + req.RequestError( + where message' = e.message)) end - fun by_url(url: String, creds: req.Credentials): Promise[RepositoryOrError] => + fun by_url( + url: String, + creds: req.Credentials) + : Promise[RepositoryOrError] + => + """ + Fetches a repository by direct API URL. + """ let p = Promise[RepositoryOrError] - let r = req.ResultReceiver[Repository](creds, - p, - RepositoryJsonConverter) + let r = + req.ResultReceiver[Repository]( + creds, + p, + RepositoryJSONConverter) req.JSONRequester.get(creds, url, r) p @@ -417,111 +457,170 @@ primitive GetRepositoryLabels """ Fetches labels for a repository as a paginated list. """ - fun apply(owner: String, + fun apply( + owner: String, repo: String, - creds: req.Credentials): Promise[(PaginatedList[Label] | req.RequestError)] + creds: req.Credentials) + : Promise[(PaginatedList[Label] | req.RequestError)] => + """ + Fetches labels by owner and repo name. + """ match \exhaustive\ ut.URITemplateParse( - "https://api.github.com/repos{/owner}{/repo}/labels") + "https://api.github.com/repos" + + "{/owner}{/repo}/labels") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("owner", owner) - .>set("repo", repo) + .> set("owner", owner) + .> set("repo", repo) let u: String val = tpl.expand(vars) by_url(u, creds) | let e: ut.URITemplateParseError => - Promise[(PaginatedList[Label] | req.RequestError)].>apply( - req.RequestError(where message' = e.message)) + Promise[(PaginatedList[Label] | req.RequestError)] + .> apply( + req.RequestError( + where message' = e.message)) end - fun by_url(url: String, - creds: req.Credentials): Promise[(PaginatedList[Label] | req.RequestError)] + fun by_url( + url: String, + creds: req.Credentials) + : Promise[(PaginatedList[Label] | req.RequestError)] => - let lc = LabelJsonConverter - let plc = PaginatedListJsonConverter[Label](creds, lc) - let p = Promise[(PaginatedList[Label] | req.RequestError)] - let r = PaginatedResultReceiver[Label](creds, p, plc) - - LinkedJsonRequester(creds, url, r) + """ + Fetches labels by direct API URL. + """ + let lc = LabelJSONConverter + let plc = + PaginatedListJSONConverter[Label](creds, lc) + let p = + Promise[(PaginatedList[Label] | req.RequestError)] + let r = + PaginatedResultReceiver[Label](creds, p, plc) + + LinkedJSONRequester(creds, url, r) p primitive GetOrganizationRepositories """ - Lists all repositories in a GitHub organization as a paginated list. + Lists all repositories in a GitHub organization as a paginated + list. """ - fun apply(org: String, - creds: req.Credentials): Promise[(PaginatedList[Repository] | req.RequestError)] + fun apply( + org: String, + creds: req.Credentials) + : Promise[(PaginatedList[Repository] | req.RequestError)] => - match \exhaustive\ ut.URITemplateParse("https://api.github.com/orgs{/org}/repos") + """ + Lists repositories for the given organization. + """ + match \exhaustive\ ut.URITemplateParse( + "https://api.github.com/orgs{/org}/repos") | let tpl: ut.URITemplate => let vars = ut.URITemplateVariables - .>set("org", org) + .> set("org", org) let u: String val = tpl.expand(vars) by_url(u, creds) | let e: ut.URITemplateParseError => - Promise[(PaginatedList[Repository] | req.RequestError)].>apply( - req.RequestError(where message' = e.message)) + Promise[ + (PaginatedList[Repository] | req.RequestError)] + .> apply( + req.RequestError( + where message' = e.message)) end - fun by_url(url: String, - creds: req.Credentials): Promise[(PaginatedList[Repository] | req.RequestError)] + fun by_url( + url: String, + creds: req.Credentials) + : Promise[ + (PaginatedList[Repository] | req.RequestError)] => - let rc = RepositoryJsonConverter - let plc = PaginatedListJsonConverter[Repository](creds, rc) - let p = Promise[(PaginatedList[Repository] | req.RequestError)] - let r = PaginatedResultReceiver[Repository](creds, p, plc) - - LinkedJsonRequester(creds, url, r) + """ + Lists repositories by direct API URL. + """ + let rc = RepositoryJSONConverter + let plc = + PaginatedListJSONConverter[Repository](creds, rc) + let p = + Promise[ + (PaginatedList[Repository] | + req.RequestError)] + let r = + PaginatedResultReceiver[Repository](creds, p, plc) + + LinkedJSONRequester(creds, url, r) p -primitive RepositoryJsonConverter is req.JSONConverter[Repository] +primitive RepositoryJSONConverter + is req.JSONConverter[Repository] """ - Converts a JSON object from the repositories API into a Repository. + Converts a JSON object from the repositories API into a + Repository. """ - fun apply(json: JSONNav, - creds: req.Credentials): Repository ? + fun apply( + json: JSONNav, + creds: req.Credentials) + : Repository ? => + """ + Converts a JSON object into a Repository. + """ let id = json("id").as_i64()? let node_id = json("node_id").as_string()? let name = json("name").as_string()? let full_name = json("full_name").as_string()? - let description = JSONNavUtil.string_or_none(json("description"))? - let owner = UserJsonConverter(json("owner"), creds)? + let description = + JSONNavUtil.string_or_none(json("description"))? + let owner = + UserJSONConverter(json("owner"), creds)? let private = json("private").as_bool()? let fork = json("fork").as_bool()? let created_at = json("created_at").as_string()? let pushed_at = json("pushed_at").as_string()? let updated_at = json("updated_at").as_string()? - let homepage = JSONNavUtil.string_or_none(json("homepage"))? - let default_branch = json("default_branch").as_string()? - let organization = try - UserJsonConverter(json("organization"), creds)? - else - None - end + let homepage = + JSONNavUtil.string_or_none(json("homepage"))? + let default_branch = + json("default_branch").as_string()? + let organization = + try + UserJSONConverter(json("organization"), creds)? + else + None + end let size = json("size").as_i64()? let forks = json("forks").as_i64()? let forks_count = json("forks_count").as_i64()? let network_count = - try json("network_count").as_i64()? else None end + try json("network_count").as_i64()? + else None + end let open_issues = json("open_issues").as_i64()? - let open_issues_count = json("open_issues_count").as_i64()? - let stargazers_count = json("stargazers_count").as_i64()? + let open_issues_count = + json("open_issues_count").as_i64()? + let stargazers_count = + json("stargazers_count").as_i64()? let subscribers_count = - try json("subscribers_count").as_i64()? else None end + try json("subscribers_count").as_i64()? + else None + end let watchers = json("watchers").as_i64()? - let watchers_count = json("watchers_count").as_i64()? - let language = JSONNavUtil.string_or_none(json("language"))? - let license = try - LicenseJsonConverter(json("license"), creds)? - else - None - end + let watchers_count = + json("watchers_count").as_i64()? + let language = + JSONNavUtil.string_or_none(json("language"))? + let license = + try + LicenseJSONConverter(json("license"), creds)? + else + None + end let archived = json("archived").as_bool()? let disabled = json("disabled").as_bool()? - let has_downloads = json("has_downloads").as_bool()? + let has_downloads = + json("has_downloads").as_bool()? let has_issues = json("has_issues").as_bool()? let has_pages = json("has_pages").as_bool()? let has_projects = json("has_projects").as_bool()? @@ -529,47 +628,72 @@ primitive RepositoryJsonConverter is req.JSONConverter[Repository] let url = json("url").as_string()? let html_url = json("html_url").as_string()? - let archive_url = json("archive_url").as_string()? - let assignees_url = json("assignees_url").as_string()? + let archive_url = + json("archive_url").as_string()? + let assignees_url = + json("assignees_url").as_string()? let blobs_url = json("blobs_url").as_string()? - let branches_url = json("branches_url").as_string()? - let comments_url = json("comments_url").as_string()? - let commits_url = json("commits_url").as_string()? - let compare_url = json("compare_url").as_string()? - let contents_url = json("contents_url").as_string()? - let contributors_url = json("contributors_url").as_string()? - let deployments_url = json("deployments_url").as_string()? - let downloads_url = json("downloads_url").as_string()? + let branches_url = + json("branches_url").as_string()? + let comments_url = + json("comments_url").as_string()? + let commits_url = + json("commits_url").as_string()? + let compare_url = + json("compare_url").as_string()? + let contents_url = + json("contents_url").as_string()? + let contributors_url = + json("contributors_url").as_string()? + let deployments_url = + json("deployments_url").as_string()? + let downloads_url = + json("downloads_url").as_string()? let events_url = json("events_url").as_string()? let forks_url = json("forks_url").as_string()? - let git_commits_url = json("git_commits_url").as_string()? - let git_refs_url = json("git_refs_url").as_string()? - let git_tags_url = json("git_tags_url").as_string()? - let issue_comment_url = json("issue_comment_url").as_string()? - let issue_events_url = json("issue_events_url").as_string()? + let git_commits_url = + json("git_commits_url").as_string()? + let git_refs_url = + json("git_refs_url").as_string()? + let git_tags_url = + json("git_tags_url").as_string()? + let issue_comment_url = + json("issue_comment_url").as_string()? + let issue_events_url = + json("issue_events_url").as_string()? let issues_url = json("issues_url").as_string()? let keys_url = json("keys_url").as_string()? let labels_url = json("labels_url").as_string()? - let languages_url = json("languages_url").as_string()? + let languages_url = + json("languages_url").as_string()? let merges_url = json("merges_url").as_string()? - let milestones_url = json("milestones_url").as_string()? - let notifications_url = json("notifications_url").as_string()? + let milestones_url = + json("milestones_url").as_string()? + let notifications_url = + json("notifications_url").as_string()? let pulls_url = json("pulls_url").as_string()? - let releases_url = json("releases_url").as_string()? - let stargazers_url = json("stargazers_url").as_string()? - let statuses_url = json("statuses_url").as_string()? - let subscribers_url = json("subscribers_url").as_string()? - let subscription_url = json("subscription_url").as_string()? + let releases_url = + json("releases_url").as_string()? + let stargazers_url = + json("stargazers_url").as_string()? + let statuses_url = + json("statuses_url").as_string()? + let subscribers_url = + json("subscribers_url").as_string()? + let subscription_url = + json("subscription_url").as_string()? let tags_url = json("tags_url").as_string()? let trees_url = json("trees_url").as_string()? let clone_url = json("clone_url").as_string()? let git_url = json("git_url").as_string()? - let mirror_url = JSONNavUtil.string_or_none(json("mirror_url"))? + let mirror_url = + JSONNavUtil.string_or_none(json("mirror_url"))? let ssh_url = json("ssh_url").as_string()? let svn_url = json("svn_url").as_string()? - Repository(creds, + Repository( + creds, id, node_id, name, diff --git a/github_rest_api/request/check_requester.pony b/github_rest_api/request/check_requester.pony index 1646532..49b2954 100644 --- a/github_rest_api/request/check_requester.pony +++ b/github_rest_api/request/check_requester.pony @@ -56,19 +56,19 @@ actor CheckRequester is courier.HTTPClientConnectionActor _connect(url) fun ref _connect(url: String) => - match uri.ParseURI(url) + match \exhaustive\ uri.ParseURI(url) | let parsed: uri.URI val => - match parsed.authority + match \exhaustive\ parsed.authority | let auth: uri.URIAuthority => _request_path = parsed.path match parsed.query | let q: String => _request_path = _request_path + "?" + q end - let port = match auth.port + let port = match \exhaustive\ auth.port | let p: U16 => p.string() | None => "443" end - let ctx = match _creds.ssl_ctx + let ctx = match \exhaustive\ _creds.ssl_ctx | let c: ssl.SSLContext val => c | None => SSLContextFactory() end diff --git a/github_rest_api/request/json_requester.pony b/github_rest_api/request/json_requester.pony index d21ca79..6f27f51 100644 --- a/github_rest_api/request/json_requester.pony +++ b/github_rest_api/request/json_requester.pony @@ -75,19 +75,19 @@ actor JSONRequester is courier.HTTPClientConnectionActor _connect(url) fun ref _connect(url: String) => - match uri.ParseURI(url) + match \exhaustive\ uri.ParseURI(url) | let parsed: uri.URI val => - match parsed.authority + match \exhaustive\ parsed.authority | let auth: uri.URIAuthority => _request_path = parsed.path match parsed.query | let q: String => _request_path = _request_path + "?" + q end - let port = match auth.port + let port = match \exhaustive\ auth.port | let p: U16 => p.string() | None => "443" end - let ctx = match _creds.ssl_ctx + let ctx = match \exhaustive\ _creds.ssl_ctx | let c: ssl.SSLContext val => c | None => SSLContextFactory() end @@ -121,7 +121,7 @@ actor JSONRequester is courier.HTTPClientConnectionActor _method, _request_path, consume hdrs, - match _body + match \exhaustive\ _body | let b: String => b.array() | None => None end) diff --git a/github_rest_api/request/no_content_requester.pony b/github_rest_api/request/no_content_requester.pony index eadeaa8..2289b33 100644 --- a/github_rest_api/request/no_content_requester.pony +++ b/github_rest_api/request/no_content_requester.pony @@ -75,19 +75,19 @@ actor NoContentRequester is courier.HTTPClientConnectionActor _connect(url) fun ref _connect(url: String) => - match uri.ParseURI(url) + match \exhaustive\ uri.ParseURI(url) | let parsed: uri.URI val => - match parsed.authority + match \exhaustive\ parsed.authority | let auth: uri.URIAuthority => _request_path = parsed.path match parsed.query | let q: String => _request_path = _request_path + "?" + q end - let port = match auth.port + let port = match \exhaustive\ auth.port | let p: U16 => p.string() | None => "443" end - let ctx = match _creds.ssl_ctx + let ctx = match \exhaustive\ _creds.ssl_ctx | let c: ssl.SSLContext val => c | None => SSLContextFactory() end diff --git a/github_rest_api/search.pony b/github_rest_api/search.pony index 84bd8af..85f15e5 100644 --- a/github_rest_api/search.pony +++ b/github_rest_api/search.pony @@ -2,44 +2,56 @@ use "json" use "promises" use req = "request" -type IssueSearchResultsOrError is (SearchResults[Issue] | req.RequestError) +type IssueSearchResultsOrError is + (SearchResults[Issue] | req.RequestError) primitive SearchIssues """ - Searches GitHub issues and pull requests using the given query string. + Searches GitHub issues and pull requests using the given query + string. """ - fun apply(query: String, - creds: req.Credentials): Promise[IssueSearchResultsOrError] + fun apply( + query: String, + creds: req.Credentials) + : Promise[IssueSearchResultsOrError] => + """ + Searches issues matching the given query string. + """ let p = Promise[IssueSearchResultsOrError] - let sc = PaginatedSearchJsonConverter[Issue](creds, IssueJsonConverter) + let sc = + PaginatedSearchJSONConverter[Issue]( + creds, IssueJSONConverter) let r = SearchResultReceiver[Issue](creds, p, sc) - let url = recover val - "https://api.github.com/search/issues" - + req.QueryParams(recover val [("q", query)] end) - end + let url = + recover val + "https://api.github.com/search/issues" + + req.QueryParams( + recover val [("q", query)] end) + end - LinkedJsonRequester(creds, url, r) + LinkedJSONRequester(creds, url, r) p class val SearchResults[A: Any val] """ - A page of search results from the GitHub search API. Contains the total - match count, an incomplete-results flag, and the items for this page. Use - `prev_page()` and `next_page()` to navigate between pages. + A page of search results from the GitHub search API. Contains + the total match count, an incomplete-results flag, and the items + for this page. Use `prev_page()` and `next_page()` to navigate + between pages. """ let _creds: req.Credentials - let _converter: PaginatedSearchJsonConverter[A] + let _converter: PaginatedSearchJSONConverter[A] let _prev_link: (String | None) let _next_link: (String | None) - let total_count: I64 let incomplete_results: Bool let items: Array[A] val - new val _create(creds: req.Credentials, + new val _create( + creds: req.Credentials, converter: req.JSONConverter[A], total_count': I64, incomplete_results': Bool, @@ -48,16 +60,21 @@ class val SearchResults[A: Any val] next_link: (String | None) = None) => _creds = creds - _converter = PaginatedSearchJsonConverter[A](creds, converter) + _converter = + PaginatedSearchJSONConverter[A](creds, converter) total_count = total_count' incomplete_results = incomplete_results' items = items' _prev_link = prev_link _next_link = next_link - fun prev_page(): (Promise[(SearchResults[A] | req.RequestError)] | None) => + fun prev_page() + : (Promise[(SearchResults[A] | req.RequestError)] + | None) + => """ - Fetches the previous page, or returns None if on the first page. + Fetches the previous page, or returns None if on the first + page. """ match \exhaustive\ _prev_link | let prev: String => @@ -66,7 +83,10 @@ class val SearchResults[A: Any val] None end - fun next_page(): (Promise[(SearchResults[A] | req.RequestError)] | None) => + fun next_page() + : (Promise[(SearchResults[A] | req.RequestError)] + | None) + => """ Fetches the next page, or returns None if on the last page. """ @@ -77,32 +97,45 @@ class val SearchResults[A: Any val] None end - fun _retrieve_link(link: String): - Promise[(SearchResults[A] | req.RequestError)] + fun _retrieve_link( + link: String) + : Promise[(SearchResults[A] | req.RequestError)] => - let p = Promise[(SearchResults[A] | req.RequestError)] - let r = SearchResultReceiver[A](_creds, p, _converter) - LinkedJsonRequester(_creds, link, r) + let p = + Promise[(SearchResults[A] | req.RequestError)] + let r = + SearchResultReceiver[A](_creds, p, _converter) + LinkedJSONRequester(_creds, link, r) p -class val PaginatedSearchJsonConverter[A: Any val] +class val PaginatedSearchJSONConverter[A: Any val] """ - Converts a JSON search response (with `total_count`, `incomplete_results`, - and `items` fields) plus Link header pagination into SearchResults. + Converts a JSON search response (with `total_count`, + `incomplete_results`, and `items` fields) plus Link header + pagination into SearchResults. """ let _creds: req.Credentials let _converter: req.JSONConverter[A] - new val create(creds: req.Credentials, converter: req.JSONConverter[A]) => + new val create( + creds: req.Credentials, + converter: req.JSONConverter[A]) + => _creds = creds _converter = converter - fun apply(json: JSONNav, + fun apply( + json: JSONNav, link_header: String, - creds: req.Credentials): SearchResults[A] ? + creds: req.Credentials) + : SearchResults[A] ? => + """ + Converts a JSON search response into SearchResults. + """ let total_count = json("total_count").as_i64()? - let incomplete = json("incomplete_results").as_bool()? + let incomplete = + json("incomplete_results").as_bool()? let items = recover trn Array[A] end for i in json("items").as_array()?.values() do @@ -110,9 +143,11 @@ class val PaginatedSearchJsonConverter[A: Any val] items.push(item) end - (let prev, let next) = _ExtractPaginationLinks(link_header) + (let prev, let next) = + _ExtractPaginationLinks(link_header) - SearchResults[A]._create(_creds, + SearchResults[A]._create( + _creds, _converter, total_count, incomplete, @@ -122,16 +157,17 @@ class val PaginatedSearchJsonConverter[A: Any val] actor SearchResultReceiver[A: Any val] """ - Receives the HTTP response for a search request and fulfills the associated - Promise with SearchResults or RequestError. + Receives the HTTP response for a search request and fulfills + the associated Promise with SearchResults or RequestError. """ let _creds: req.Credentials let _p: Promise[(SearchResults[A] | req.RequestError)] - let _converter: PaginatedSearchJsonConverter[A] + let _converter: PaginatedSearchJSONConverter[A] - new create(creds: req.Credentials, + new create( + creds: req.Credentials, p: Promise[(SearchResults[A] | req.RequestError)], - c: PaginatedSearchJsonConverter[A]) + c: PaginatedSearchJSONConverter[A]) => _creds = creds _p = p @@ -141,12 +177,18 @@ actor SearchResultReceiver[A: Any val] try _p(_converter(json, link_header, _creds)?) else - let m = recover val - "Unable to convert json for " + req.JSONTypeString(json) - end + let m = + recover val + "Unable to convert json for " + + req.JSONTypeString(json) + end _p(req.RequestError(where message' = m)) end - be failure(status: U16, response_body: String, message: String) => + be failure( + status: U16, + response_body: String, + message: String) + => _p(req.RequestError(status, response_body, message)) diff --git a/github_rest_api/user.pony b/github_rest_api/user.pony index 6c5d51e..2dc6baa 100644 --- a/github_rest_api/user.pony +++ b/github_rest_api/user.pony @@ -67,11 +67,14 @@ class val User user_type = user_type' site_admin = site_admin' -primitive UserJsonConverter is req.JSONConverter[User] +primitive UserJSONConverter is req.JSONConverter[User] """ Converts a JSON object into a User. """ fun apply(json: JSONNav, creds: req.Credentials): User ? => + """ + Parses the JSON representation of a user account. + """ let login = json("login").as_string()? let id = json("id").as_i64()? let node_id = json("node_id").as_string()? @@ -87,11 +90,13 @@ primitive UserJsonConverter is req.JSONConverter[User] let organizations_url = json("organizations_url").as_string()? let repos_url = json("repos_url").as_string()? let events_url = json("events_url").as_string()? - let received_events_url = json("received_events_url").as_string()? + let received_events_url = + json("received_events_url").as_string()? let user_type = json("type").as_string()? let site_admin = json("site_admin").as_bool()? - User(creds, + User( + creds, login, id, node_id,