aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Edgecumbe <git@esotericnonsense.com>2019-10-28 18:37:11 +0100
committerDaniel Edgecumbe <git@esotericnonsense.com>2019-10-28 18:37:11 +0100
commita802d8ef5d1e08b1d3561145189f9ba5db84efd6 (patch)
tree68f7a5ae197b5c71e6e03d2381581a79f51343ee
parente15dc729da01f8b449e4dcc4ae0e6636ce2a5675 (diff)
Deserialize the errorCode of a JSON-RPC exception
-rwxr-xr-xgenapi/main.py75
-rw-r--r--src/generated_exceptions.rs68
-rw-r--r--src/json_rpc.rs3
-rw-r--r--src/lib.rs1
-rw-r--r--src/result.rs4
5 files changed, 148 insertions, 3 deletions
diff --git a/genapi/main.py b/genapi/main.py
index 07f243b..b84e556 100755
--- a/genapi/main.py
+++ b/genapi/main.py
@@ -77,6 +77,7 @@ class ExceptionType(DataClassJsonMixin):
"""An exception type as per the BF API"""
name: str
+ description: Optional[str]
prefix: str
params: List[Param]
@@ -398,7 +399,9 @@ def parse_exceptionType(el: Element) -> ExceptionType:
raise NotImplementedError(child.tag)
- return ExceptionType(name=name, prefix=prefix, params=params)
+ return ExceptionType(
+ name=name, description=description, prefix=prefix, params=params
+ )
def parse_simpleType(el: Element) -> SimpleType:
@@ -673,9 +676,63 @@ pub {function_signature} {{ {function_interior} }}"""
return RustOperations(request_structs=request_structs, functions=functions)
+def generate_rust_exceptions(
+ exception_types: List[ExceptionType]
+) -> List[str]:
+ """
+ Return API bindings for the operations.
+ For the time being the function bodies are just empty.
+ """
+
+ # def format_param(param: Param):
+ # return f"""#[serde(rename = "{exception_type.prefix}-{(param._id):04d}")]
+ # {aping_name_to_rust_name(param.name)}"""
+
+ exceptions: List[str] = []
+ for exception_type in exception_types: # type: ExceptionType
+ # TODO
+ # if exception_type.description is not None:
+ # exceptions.append(f"/// {exception_type.description}")
+
+ for param in exception_type.params:
+ if param.name != "errorCode":
+ # TODO do not ignore
+ continue
+
+ if param.values is None:
+ rust_type: str = python_type_to_rust_type(param._type)
+ exceptions.append(f"pub type {param.name} = {rust_type};")
+ continue
+ # All of the enums are stringly typed, this is a sanity check
+ assert param._type == "string"
+
+ variants: List[str] = []
+ for value in param.values:
+ subvariant: List[str] = []
+ if value.description is not None:
+ subvariant.append(f"/// {value.description}")
+ subvariant.append(
+ f"""#[serde(rename = "{exception_type.prefix}-{(value._id):04d}")]
+{value.name}"""
+ )
+ variants.append("\n".join(subvariant))
+
+ variants_str = ",\n".join(variants)
+ exceptions.append(
+ f"""#[derive(Debug, Deserialize)]
+ pub enum {param.name} {{
+ {variants_str}
+ }}"""
+ )
+ continue
+
+ return exceptions
+
+
def main() -> None:
tree = parse("SportsAPING.patched.xml")
aping: APING = parse_aping(tree.getroot())
+
# print(aping.to_json())
header = [
@@ -696,6 +753,9 @@ def main() -> None:
aping.simple_types
)
rust_data_types: List[str] = generate_rust_data_types(aping.data_types)
+ rust_exceptions: List[str] = generate_rust_exceptions(
+ aping.exception_types
+ )
with open("../src/generated_types.rs", "w") as f:
for l in header:
f.write(l + "\n")
@@ -746,6 +806,19 @@ def main() -> None:
for l in rust_operations.request_structs:
f.write(l + "\n")
+ with open("../src/generated_exceptions.rs", "w") as f:
+ for l in header:
+ f.write(l + "\n")
+ a = [
+ "#![allow(non_camel_case_types)]",
+ "#![allow(non_snake_case)]",
+ "use serde::Deserialize;",
+ ]
+ for l in a:
+ f.write(l + "\n")
+ for l in rust_exceptions:
+ f.write(l + "\n")
+
if __name__ == "__main__":
main()
diff --git a/src/generated_exceptions.rs b/src/generated_exceptions.rs
new file mode 100644
index 0000000..7c0d394
--- /dev/null
+++ b/src/generated_exceptions.rs
@@ -0,0 +1,68 @@
+//! # automatically generated
+//! This module has been automatically generated by botfair
+//! from the Betfair APING documentation at
+//! https://docs.developer.betfair.com
+//!
+//! Any documentation here has been generated directly from the API
+//! docs.
+
+#![allow(non_camel_case_types)]
+#![allow(non_snake_case)]
+use serde::Deserialize;
+#[derive(Debug, Deserialize)]
+pub enum errorCode {
+ /// The operation requested too much data
+ #[serde(rename = "ANGX-0001")]
+ TOO_MUCH_DATA,
+ /// Invalid input data
+ #[serde(rename = "ANGX-0002")]
+ INVALID_INPUT_DATA,
+ /// The session token passed is invalid
+ #[serde(rename = "ANGX-0003")]
+ INVALID_SESSION_INFORMATION,
+ /// An application key is required for this operation
+ #[serde(rename = "ANGX-0004")]
+ NO_APP_KEY,
+ /// A session token is required for this operation
+ #[serde(rename = "ANGX-0005")]
+ NO_SESSION,
+ /// An unexpected internal error occurred that prevented successful request processing.
+ #[serde(rename = "ANGX-0006")]
+ UNEXPECTED_ERROR,
+ /// The application key passed is invalid
+ #[serde(rename = "ANGX-0007")]
+ INVALID_APP_KEY,
+ /// There are too many pending requests
+ #[serde(rename = "ANGX-0008")]
+ TOO_MANY_REQUESTS,
+ /// The service is currently too busy to service this request
+ #[serde(rename = "ANGX-0009")]
+ SERVICE_BUSY,
+ /// Internal call to downstream service timed out
+ #[serde(rename = "ANGX-0010")]
+ TIMEOUT_ERROR,
+ /// The application key creation has failed
+ #[serde(rename = "ANGX-0011")]
+ APP_KEY_CREATION_FAILED,
+ /// The application name specified already exists
+ #[serde(rename = "ANGX-0012")]
+ DUPLICATE_APP_NAME,
+ /// The application name specified is too long
+ #[serde(rename = "ANGX-0013")]
+ APP_CREATION_FAILED,
+ /// The request has exceeded the maximum allowed size
+ #[serde(rename = "ANGX-0014")]
+ REQUEST_SIZE_EXCEEDS_LIMIT,
+ /// The access to this functionality is not allowed
+ #[serde(rename = "ANGX-0015")]
+ ACCESS_DENIED,
+ /// Provided market group id does not identify a known market group
+ #[serde(rename = "ANGX-0016")]
+ INVALID_MARKET_GROUP,
+ /// Unable to delete/update limit as it doesn't exist
+ #[serde(rename = "ANGX-0017")]
+ EXPOSURE_LIMIT_NOT_EXIST,
+ /// Unable to unblock market group after exposure limit breach, market group is not blocked
+ #[serde(rename = "ANGX-0018")]
+ MARKET_GROUP_NOT_BLOCKED,
+}
diff --git a/src/json_rpc.rs b/src/json_rpc.rs
index 30520cc..b50623a 100644
--- a/src/json_rpc.rs
+++ b/src/json_rpc.rs
@@ -14,6 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with botfair. If not, see <http://www.gnu.org/licenses/>.
+use crate::generated_exceptions::errorCode;
use crate::result::{Error, Result};
use serde::{Deserialize, Serialize};
@@ -40,7 +41,7 @@ impl<T> RpcRequest<T> {
#[derive(Debug, Deserialize)]
pub struct RpcError {
code: i32,
- message: String,
+ message: errorCode,
}
#[derive(Deserialize)]
diff --git a/src/lib.rs b/src/lib.rs
index ea2af07..ba2aa95 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -95,6 +95,7 @@
extern crate log;
pub mod client;
+pub mod generated_exceptions;
mod generated_methods;
mod generated_requests;
pub mod generated_types;
diff --git a/src/result.rs b/src/result.rs
index d885312..ab5d6b8 100644
--- a/src/result.rs
+++ b/src/result.rs
@@ -14,11 +14,13 @@
// You should have received a copy of the GNU Affero General Public License
// along with botfair. If not, see <http://www.gnu.org/licenses/>.
+use crate::generated_exceptions::errorCode;
+
#[derive(Debug)]
pub enum Error {
Io(std::io::Error),
Reqwest(reqwest::Error),
- APINGException(String), // TODO generated_exceptions.rs
+ APINGException(errorCode),
BFLoginFailure(String),
BFKeepAliveFailure(crate::client::KeepAliveError), // could be an enum
General(String),