BVB Source Codes

voltron Show api.py Source code

Return Download voltron: download api.py Source code - Download voltron Source code - Type:.py
  1. import os
  2. import logging
  3. import socket
  4. import select
  5. import threading
  6. import logging
  7. import logging.config
  8. import json
  9. import inspect
  10. import base64
  11. import six
  12.  
  13. from collections import defaultdict
  14.  
  15. from scruffy.plugin import Plugin
  16.  
  17. import voltron
  18. from .plugin import APIPlugin
  19.  
  20. log = logging.getLogger('api')
  21.  
  22. version = 1.1
  23.  
  24.  
  25. class InvalidRequestTypeException(Exception):
  26.     """
  27.    Exception raised when the client is requested to send an invalid request type.
  28.    """
  29.     pass
  30.  
  31.  
  32. class InvalidDebuggerHostException(Exception):
  33.     """
  34.    Exception raised when the debugger host is invalid.
  35.    """
  36.     pass
  37.  
  38.  
  39. class InvalidViewNameException(Exception):
  40.     """
  41.    Exception raised when an invalid view name is specified.
  42.    """
  43.     pass
  44.  
  45.  
  46. class InvalidMessageException(Exception):
  47.     """
  48.    Exception raised when an invalid API message is received.
  49.    """
  50.     pass
  51.  
  52.  
  53. class ServerSideOnlyException(Exception):
  54.     """
  55.    Exception raised when a server-side method is called on an APIMessage
  56.    subclass that exists on the client-side.
  57.  
  58.    See @server_side decorator.
  59.    """
  60.     pass
  61.  
  62.  
  63. class ClientSideOnlyException(Exception):
  64.     """
  65.    Exception raised when a server-side method is called on an APIMessage
  66.    subclass that exists on the client-side.
  67.  
  68.    See @client_side decorator.
  69.    """
  70.     pass
  71.  
  72.  
  73. class DebuggerNotPresentException(Exception):
  74.     """
  75.    Raised when an APIRequest is dispatched without a valid debugger present.
  76.    """
  77.     pass
  78.  
  79.  
  80. class NoSuchTargetException(Exception):
  81.     """
  82.    Raised when an APIRequest specifies an invalid target.
  83.    """
  84.     pass
  85.  
  86.  
  87. class TargetBusyException(Exception):
  88.     """
  89.    Raised when an APIRequest specifies a target that is currently busy and
  90.    cannot be queried.
  91.    """
  92.     pass
  93.  
  94.  
  95. class MissingFieldError(Exception):
  96.     """
  97.    Raised when an APIMessage is validated and has a required field missing.
  98.    """
  99.     pass
  100.  
  101.  
  102. class NoSuchThreadException(Exception):
  103.     """
  104.    Raised when the specified thread ID or index does not exist.
  105.    """
  106.     pass
  107.  
  108.  
  109. class UnknownArchitectureException(Exception):
  110.     """
  111.    Raised when the debugger host is running in an unknown architecture.
  112.    """
  113.     pass
  114.  
  115.  
  116. class BlockingNotSupportedError(Exception):
  117.     """
  118.    Raised when a view that does not support blocking connects to a debugger
  119.    host that does not support async mode.
  120.    """
  121.     pass
  122.  
  123.  
  124. def server_side(func):
  125.     """
  126.    Decorator to designate an API method applicable only to server-side
  127.    instances.
  128.  
  129.    This allows us to use the same APIRequest and APIResponse subclasses on the
  130.    client and server sides without too much confusion.
  131.    """
  132.     def inner(*args, **kwargs):
  133.         if args and hasattr(args[0], 'is_server') and not voltron.debugger:
  134.             raise ServerSideOnlyException("This method can only be called on a server-side instance")
  135.         return func(*args, **kwargs)
  136.     return inner
  137.  
  138.  
  139. def client_side(func):
  140.     """
  141.    Decorator to designate an API method applicable only to client-side
  142.    instances.
  143.  
  144.    This allows us to use the same APIRequest and APIResponse subclasses on the
  145.    client and server sides without too much confusion.
  146.    """
  147.     def inner(*args, **kwargs):
  148.         if args and hasattr(args[0], 'is_server') and voltron.debugger:
  149.             raise ClientSideOnlyException("This method can only be called on a client-side instance")
  150.         return func(*args, **kwargs)
  151.     return inner
  152.  
  153.  
  154. def cast_b(val):
  155.     if isinstance(val, six.binary_type):
  156.         return val
  157.     elif isinstance(val, six.text_type):
  158.         return val.encode('latin1')
  159.     return six.binary_type(val)
  160.  
  161.  
  162. def cast_s(val):
  163.     if type(val) == six.text_type:
  164.         return val
  165.     elif type(val) == six.binary_type:
  166.         return val.decode('latin1')
  167.     return six.text_type(val)
  168.  
  169.  
  170. class APIMessage(object):
  171.     """
  172.    Top-level API message class.
  173.    """
  174.     _top_fields = ['type']
  175.     _fields = {}
  176.     _encode_fields = []
  177.  
  178.     type = None
  179.  
  180.     def __init__(self, data=None, *args, **kwargs):
  181.         # process any data that was passed in
  182.         if data:
  183.             self.from_json(data)
  184.  
  185.         # any other kwargs are treated as field values
  186.         for field in kwargs:
  187.             setattr(self, field, kwargs[field])
  188.  
  189.     def __str__(self):
  190.         """
  191.        Return a string (JSON) representation of the API message properties.
  192.        """
  193.         return self.to_json()
  194.  
  195.     def to_dict(self):
  196.         """
  197.        Return a transmission-safe dictionary representation of the API message properties.
  198.        """
  199.         d = {field: getattr(self, field) for field in self._top_fields if hasattr(self, field)}
  200.  
  201.         # set values of data fields
  202.         d['data'] = {}
  203.         for field in self._fields:
  204.             if hasattr(self, field):
  205.                 # base64 encode the field for transmission if necessary
  206.                 if field in self._encode_fields:
  207.                     val = getattr(self, field)
  208.                     if val:
  209.                         val = cast_s(base64.b64encode(cast_b(val)))
  210.                     d['data'][field] = val
  211.                 else:
  212.                     d['data'][field] = getattr(self, field)
  213.  
  214.         return d
  215.  
  216.     def from_dict(self, d):
  217.         """
  218.        Initialise an API message from a transmission-safe dictionary.
  219.        """
  220.         for key in d:
  221.             if key == 'data':
  222.                 for dkey in d['data']:
  223.                     if dkey in self._encode_fields:
  224.                         setattr(self, str(dkey), base64.b64decode(d['data'][dkey]))
  225.                     else:
  226.                         setattr(self, str(dkey), d['data'][dkey])
  227.             else:
  228.                 setattr(self, str(key), d[key])
  229.  
  230.     def to_json(self):
  231.         """
  232.        Return a JSON representation of the API message properties.
  233.        """
  234.         return json.dumps(self.to_dict())
  235.  
  236.     def from_json(self, data):
  237.         """
  238.        Initialise an API message from a JSON representation.
  239.        """
  240.         try:
  241.             d = json.loads(data)
  242.         except ValueError:
  243.             raise InvalidMessageException()
  244.         self.from_dict(d)
  245.  
  246.     def __getattr__(self, name):
  247.         """
  248.        Attribute accessor.
  249.  
  250.        If a defined field is requested that doesn't have a value set,
  251.        return None.
  252.        """
  253.         if name in self._fields:
  254.             return None
  255.  
  256.     def validate(self):
  257.         """
  258.        Validate the message.
  259.  
  260.        Ensure all the required fields are present and not None.
  261.        """
  262.         required_fields = list(filter(lambda x: self._fields[x], self._fields.keys()))
  263.         for field in (self._top_fields + required_fields):
  264.             if not hasattr(self, field) or hasattr(self, field) and getattr(self, field) == None:
  265.                 raise MissingFieldError(field)
  266.  
  267.  
  268. class APIRequest(APIMessage):
  269.     """
  270.    An API request object. Contains functions and accessors common to all API
  271.    request types.
  272.  
  273.    Subclasses of APIRequest are used on both the client and server sides. On
  274.    the server side they are instantiated by Server's `handle_request()`
  275.    method. On the client side they are instantiated by whatever class is doing
  276.    the requesting (probably a view class).
  277.    """
  278.     _top_fields = ['type', 'request', 'block', 'timeout']
  279.     _fields = {}
  280.  
  281.     type = 'request'
  282.     request = None
  283.     block = False
  284.     timeout = 10
  285.  
  286.     response = None
  287.     wait_event = None
  288.     timed_out = False
  289.  
  290.     @server_side
  291.     def dispatch(self):
  292.         """
  293.        In concrete subclasses this method will actually dispatch the request
  294.        to the debugger host and return a response. In this case it raises an
  295.        exception.
  296.        """
  297.         raise NotImplementedError("Subclass APIRequest")
  298.  
  299.     @server_side
  300.     def wait(self):
  301.         """
  302.        Wait for the request to be dispatched.
  303.        """
  304.         self.wait_event = threading.Event()
  305.         timeout = int(self.timeout) if self.timeout else None
  306.         self.timed_out = not self.wait_event.wait(timeout)
  307.  
  308.     def signal(self):
  309.         """
  310.        Signal that the request has been dispatched and can return.
  311.        """
  312.         self.wait_event.set()
  313.  
  314.  
  315. class APIBlockingRequest(APIRequest):
  316.     """
  317.    An API request that blocks by default.
  318.    """
  319.     block = True
  320.  
  321.  
  322. class APIResponse(APIMessage):
  323.     """
  324.    An API response object. Contains functions and accessors common to all API
  325.    response types.
  326.  
  327.    Subclasses of APIResponse are used on both the client and server sides. On
  328.    the server side they are instantiated by the APIRequest's `dispatch` method
  329.    in order to serialise and send to the client. On the client side they are
  330.    instantiated by the Client class and returned by `send_request`.
  331.    """
  332.     _top_fields = ['type', 'status']
  333.     _fields = {}
  334.  
  335.     type = 'response'
  336.     status = None
  337.  
  338.     @property
  339.     def is_success(self):
  340.         return self.status == 'success'
  341.  
  342.     @property
  343.     def is_error(self):
  344.         return self.status == 'error'
  345.  
  346.     def __repr__(self):
  347.         return "<%s: success = %s, error = %s, body: %s>" % (
  348.                 str(self.__class__),
  349.                 self.is_success,
  350.                 self.is_error,
  351.                 {f: getattr(self, f) for f in self._top_fields + list(self._fields.keys())}
  352.         )
  353.  
  354.  
  355. class APISuccessResponse(APIResponse):
  356.     """
  357.    A generic API success response.
  358.    """
  359.     status = 'success'
  360.  
  361.  
  362. class APIErrorResponse(APIResponse):
  363.     """
  364.    A generic API error response.
  365.    """
  366.     _fields = {'code': True, 'message': True}
  367.  
  368.     status = 'error'
  369.  
  370.     @property
  371.     def timed_out(self):
  372.         return self.code == APITimedOutErrorResponse.code
  373.  
  374.  
  375. class APIGenericErrorResponse(APIErrorResponse):
  376.     code = 0x1000
  377.     message = "An error occurred"
  378.  
  379.     def __init__(self, message=None):
  380.         super(APIGenericErrorResponse, self).__init__()
  381.         if message:
  382.             self.message = message
  383.  
  384.  
  385. class APIInvalidRequestErrorResponse(APIErrorResponse):
  386.     code = 0x1001
  387.     message = "Invalid API request"
  388.  
  389.  
  390. class APIPluginNotFoundErrorResponse(APIErrorResponse):
  391.     code = 0x1002
  392.     message = "Plugin was not found for request"
  393.  
  394.  
  395. class APIDebuggerHostNotSupportedErrorResponse(APIErrorResponse):
  396.     code = 0x1003
  397.     message = "The targeted debugger host is not supported by this plugin"
  398.  
  399.  
  400. class APITimedOutErrorResponse(APIErrorResponse):
  401.     code = 0x1004
  402.     message = "The request timed out"
  403.  
  404.  
  405. class APIDebuggerNotPresentErrorResponse(APIErrorResponse):
  406.     code = 0x1004
  407.     message = "No debugger host was found"
  408.  
  409.  
  410. class APINoSuchTargetErrorResponse(APIErrorResponse):
  411.     code = 0x1005
  412.     message = "No such target"
  413.  
  414.  
  415. class APITargetBusyErrorResponse(APIErrorResponse):
  416.     code = 0x1006
  417.     message = "Target busy"
  418.  
  419.  
  420. class APIMissingFieldErrorResponse(APIGenericErrorResponse):
  421.     code = 0x1007
  422.     message = "Missing field"
  423.  
  424.  
  425. class APIEmptyResponseErrorResponse(APIGenericErrorResponse):
  426.     code = 0x1008
  427.     message = "Empty response"
  428.  
  429.  
  430. class APIServerNotRunningErrorResponse(APIGenericErrorResponse):
  431.     code = 0x1009
  432.     message = "Server is not running"
  433.  
downloadapi.py Source code - Download voltron Source code
Related Source Codes/Software:
IGListKit - A data-driven UICollectionView framework for build... 2017-01-11
androidmvp - MVP Android Example 2017-01-11
svelte - The magical disappearing UI framework ... 2017-01-11
kcptun - A Simple UDP Tunnel Based On KCP 2017-01-11
poisontap - Exploits locked/password protected computers over ... 2017-01-10
ecma262 - Status, process, and documents for ECMA262 ... 2017-01-11
react-native-elements - React Native Elements UI Toolkit 2017-01-11
tensorflow-zh - Google new open source ai system TensorFlow Chines... 2017-01-11
forum - Blue light (the Lantern) the official BBS 2017-01-11
socketcluster - Highly scalable realtime framework ... 2017-01-11
mongo-express - Web-based MongoDB admin interface, written with No... 2017-05-17
XCL-Charts - Android charting libraries (XCL-Charts is a free c... 2017-05-17
scrollMonitor - A simple and fast API to monitor elements as you s... 2017-05-16
XCDYouTubeKit - YouTube video player for iOS, tvOS and macOS 2017-05-16
rails-erd - Generate Entity-Relationship Diagrams for Rails ap... 2017-05-16
np - A better `npm publish` 2017-05-16
android - Smartisan open source code for full build.(repo ma... 2017-05-16
word_cloud - A little word cloud generator in Pytho 2017-05-16
mobileplayer-ios - 2017-05-16
Destroy-Windows-10-Spying - Destroy Windows Spying tool ... 2017-05-15

 Back to top