diff --git a/Cargo.toml b/Cargo.toml
index c4f60196e8..80b5201f71 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -19,6 +19,7 @@ path = "src/rust/lib.rs"
[dependencies]
clap = "2"
+http = "^0.2"
hyper = "0.14"
mime = "0.2"
rustc-serialize = "*"
@@ -30,4 +31,4 @@ strsim = "*"
tokio = "^ 1.0"
hyper-rustls = "^0.22"
itertools = "^ 0.10"
-tower-service = "^0.3"
\ No newline at end of file
+tower-service = "^0.3"
diff --git a/changelog.md b/changelog.md
index 5084d83410..dda9907adf 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,11 @@
+## api/cli-vNEXT (YYYY-MM-DD)
+
+- New `GetToken` trait for custom ways of specifying a token. The latter can now be a String or be
+ `NoToken` as well.
+- Upgrade `mkdocs` to a more recent version that doesn't break in more recent python interpreters.
+
## api/cli-v3.0.0 (2022-3-8)
- Support for yup-oauth 0.6
diff --git a/requirements.txt b/requirements.txt
index 7ef6fdf2a5..89ad107608 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,6 +1,6 @@
-mako==1.1.4
+mako==1.2.2
pyyaml<6
-mkdocs==0.11
+mkdocs==1.3.1
pytest
pytest-cov
codecov
diff --git a/src/generator/templates/Cargo.toml.mako b/src/generator/templates/Cargo.toml.mako
index 1d23f7138c..7885c43435 100644
--- a/src/generator/templates/Cargo.toml.mako
+++ b/src/generator/templates/Cargo.toml.mako
@@ -26,12 +26,16 @@ path = "src/main.rs"
% endif
[dependencies]
+## TODO: temporary, remove when yup-oauth2 is optional
+anyhow = "^ 1.0"
hyper-rustls = "0.23.0"
## Must match the one hyper uses, otherwise there are duplicate similarly named `Mime` structs
mime = "^ 0.2.0"
serde = "^ 1.0"
serde_json = "^ 1.0"
serde_derive = "^ 1.0"
+## TODO: Make yup-oauth2 optional
+## yup-oauth2 = { version = "^ 7.0", optional = true }
yup-oauth2 = "^ 7.0"
itertools = "^ 0.10"
% for dep in cargo.get('dependencies', list()):
@@ -41,7 +45,7 @@ ${dep}
<%
api_name = util.library_name()
crate_name_we_depend_on = None
-
+
if make.depends_on_suffix is not None:
crate_name_we_depend_on = library_to_crate_name(api_name, suffix=make.depends_on_suffix)
%>\
@@ -53,3 +57,7 @@ ${dep}
path = "../${api_name}"
version = "${util.crate_version()}"
% endif
+
+## TODO: Make yup-oauth2 optional
+# [features]
+# default = ["yup-oauth2"]
diff --git a/src/generator/templates/api/api.rs.mako b/src/generator/templates/api/api.rs.mako
index b5dfd40a1d..cc81bcf07d 100644
--- a/src/generator/templates/api/api.rs.mako
+++ b/src/generator/templates/api/api.rs.mako
@@ -30,7 +30,7 @@ use http::Uri;
use hyper::client::connect;
use tokio::io::{AsyncRead, AsyncWrite};
use tower_service;
-use crate::client;
+use crate::{client, client::GetToken};
// ##############
// UTILITIES ###
@@ -55,7 +55,7 @@ ${lib.hub_usage_example(c)}\
#[derive(Clone)]
pub struct ${hub_type}${ht_params} {
pub client: hyper::Client,
- pub auth: oauth2::authenticator::Authenticator,
+ pub auth: Box,
_user_agent: String,
_base_url: String,
_root_url: String,
@@ -65,10 +65,10 @@ impl<'a, ${', '.join(HUB_TYPE_PARAMETERS)}> client::Hub for ${hub_type}${ht_para
impl<'a, ${', '.join(HUB_TYPE_PARAMETERS)}> ${hub_type}${ht_params} {
- pub fn new(client: hyper::Client, authenticator: oauth2::authenticator::Authenticator) -> ${hub_type}${ht_params} {
+ pub fn new(client: hyper::Client, auth: A) -> ${hub_type}${ht_params} {
${hub_type} {
client,
- auth: authenticator,
+ auth: Box::new(auth),
_user_agent: "${default_user_agent}".to_string(),
_base_url: "${baseUrl}".to_string(),
_root_url: "${rootUrl}".to_string(),
diff --git a/src/generator/templates/api/lib/mbuild.mako b/src/generator/templates/api/lib/mbuild.mako
index 18007e04fa..7ba7c06a75 100644
--- a/src/generator/templates/api/lib/mbuild.mako
+++ b/src/generator/templates/api/lib/mbuild.mako
@@ -706,10 +706,21 @@ else {
loop {
% if default_scope:
- let token = match ${auth_call}.token(&self.${api.properties.scopes}.keys().collect::>()[..]).await {
- Ok(token) => token.clone(),
+ let token = match ${auth_call}.get_token(&self.${api.properties.scopes}.keys().map(String::as_str).collect::>()[..]).await {
+ // TODO: remove Ok / Err branches
+ Ok(Some(token)) => token.clone(),
+ Ok(None) => {
+ let err = oauth2::Error::OtherError(anyhow::Error::msg("unknown error occurred while generating oauth2 token"));
+ match dlg.token(&err) {
+ Some(token) => token,
+ None => {
+ ${delegate_finish}(false);
+ return Err(client::Error::MissingToken(err))
+ }
+ }
+ }
Err(err) => {
- match dlg.token(&err) {
+ match dlg.token(&err) {
Some(token) => token,
None => {
${delegate_finish}(false);
diff --git a/src/generator/templates/cli/mkdocs.yml.mako b/src/generator/templates/cli/mkdocs.yml.mako
index 6566f5ad77..251bad2199 100644
--- a/src/generator/templates/cli/mkdocs.yml.mako
+++ b/src/generator/templates/cli/mkdocs.yml.mako
@@ -14,11 +14,12 @@ repo_url: ${util.github_source_root_url()}
docs_dir: ${mkdocs.docs_dir}
site_dir: ${mkdocs.site_dir}
-pages:
-- ['index.md', 'Home']
+nav:
+- Home: 'index.md'
% for resource in sorted(c.rta_map.keys()):
+- '${pretty(resource)}':
% for method in sorted(c.rta_map[resource]):
-- ['${subcommand_md_filename(resource, method)}', '${pretty(resource)}', '${pretty(method)}']
+ - '${pretty(method)}': '${subcommand_md_filename(resource, method)}'
% endfor # each method
% endfor # each resource
diff --git a/src/rust/api/client.rs b/src/rust/api/client.rs
index 1c5e04cdbc..25b2459830 100644
--- a/src/rust/api/client.rs
+++ b/src/rust/api/client.rs
@@ -1,7 +1,9 @@
use std::error;
use std::error::Error as StdError;
use std::fmt::{self, Display};
+use std::future::Future;
use std::io::{self, Cursor, Read, Seek, SeekFrom, Write};
+use std::pin::Pin;
use std::str::FromStr;
use std::thread::sleep;
use std::time::Duration;
@@ -105,12 +107,13 @@ pub trait Delegate: Send {
None
}
+ // TODO: Remove oauth2::Error
/// Called whenever the Authenticator didn't yield a token. The delegate
/// may attempt to provide one, or just take it as a general information about the
/// impending failure.
/// The given Error provides information about why the token couldn't be acquired in the
/// first place
- fn token(&mut self, err: &oauth2::Error) -> Option {
+ fn token(&mut self, err: &oauth2::Error) -> Option {
let _ = err;
None
}
@@ -227,6 +230,7 @@ pub enum Error {
/// Neither through the authenticator, nor through the Delegate.
MissingAPIKey,
+ // TODO: Remove oauth2::Error
/// We required a Token, but didn't get one from the Authenticator
MissingToken(oauth2::Error),
@@ -272,6 +276,7 @@ impl Display for Error {
writeln!(f, "Bad Request: {}", message)?;
Ok(())
}
+ // TODO: Remove oauth2::Error
Error::MissingToken(ref err) => {
writeln!(f, "Token retrieval failed with error: {}", err)
}
@@ -785,3 +790,75 @@ pub async fn get_body_as_string(res_body: &mut hyper::Body) -> String {
let res_body_string = String::from_utf8_lossy(&res_body_buf);
res_body_string.to_string()
}
+
+// TODO: Simplify this to Option
+type TokenResult = std::result::Result