Ejemplo n.º 1
0
class MoviesSoapService(spyne.Service):
    __soap_target_namespace__ = 'MyNS'
    __soap_server_address__ = '/soap/movies'
    __service_url_path__ = '/soap/movies'
    __in_protocol__ = Soap11(validator='lxml')
    __out_protocol__ = Soap11()

    @spyne.srpc(Unicode(default=''),
                Unicode(default=''),
                _returns=Array(Movie))
    def getMovieSoap(option, search):
        m = []
        if option == '' or search == '':
            for movie in movies:
                m.append(
                    Movie(ID=movie["ID"],
                          Title=movie["Title"],
                          Genre=movie["Genre"],
                          Rating=movie["Rating"],
                          Release_date=movie["Release_date"],
                          Album_ID=movie["Album_ID"]))
        elif option == "ID":
            for movie in movies:
                if (movie["ID"] == search):
                    m.append(
                        Movie(ID=movie["ID"],
                              Title=movie["Title"],
                              Genre=movie["Genre"],
                              Rating=movie["Rating"],
                              Release_date=movie["Release_date"],
                              Album_ID=movie["Album_ID"]))
        elif option == "Title":
            for movie in movies:
                if (re.search(search, movie["Title"], re.IGNORECASE)):
                    m.append(
                        Movie(ID=movie["ID"],
                              Title=movie["Title"],
                              Genre=movie["Genre"],
                              Rating=movie["Rating"],
                              Release_date=movie["Release_date"],
                              Album_ID=movie["Album_ID"]))
        else:
            for movie in movies:
                m.append(
                    Movie(ID=movie["ID"],
                          Title=movie["Title"],
                          Genre=movie["Genre"],
                          Rating=movie["Rating"],
                          Release_date=movie["Release_date"],
                          Album_ID=movie["Album_ID"]))

        return m

    @spyne.srpc(Unicode, _returns=Array(Movie))
    def getMovieByIdSoap(Id):
        m = []
        for movie in movies:
            if (movie["ID"] == Id):
                m.append(
                    Movie(ID=movie["ID"],
                          Title=movie["Title"],
                          Genre=movie["Genre"],
                          Rating=movie["Rating"],
                          Release_date=movie["Release_date"],
                          Album_ID=movie["Album_ID"]))
        return m

    @spyne.srpc(Unicode, _returns=Array(Movie))
    def getMovieByTitleSoap(Title):
        m = []
        for movie in movies:
            if (re.search(Title, movie["Title"], re.IGNORECASE)):
                m.append(
                    Movie(ID=movie["ID"],
                          Title=movie["Title"],
                          Genre=movie["Genre"],
                          Rating=movie["Rating"],
                          Release_date=movie["Release_date"],
                          Album_ID=movie["Album_ID"]))
        return m

    @spyne.srpc(Unicode, _returns=Array(Movie))
    def getMovieByGenreSoap(Genre):
        m = []
        for movie in movies:
            if (movie["Genre"] == Genre):
                m.append(
                    Movie(ID=movie["ID"],
                          Title=movie["Title"],
                          Genre=movie["Genre"],
                          Rating=movie["Rating"],
                          Release_date=movie["Release_date"],
                          Album_ID=movie["Album_ID"]))
        return m

    @spyne.srpc(Unicode, _returns=Array(Movie))
    def getMovieByRatingSoap(Rating):
        m = []
        if (re.search('^[0-9](\.[0-9]*)?$', Rating)):
            for movie in movies:
                if (re.search('^[0-9](\.[0-9]*)?$', movie['Rating'])):
                    if (float(movie['Rating']) > float(Rating)):
                        m.append(
                            Movie(ID=movie["ID"],
                                  Title=movie["Title"],
                                  Genre=movie["Genre"],
                                  Rating=movie["Rating"],
                                  Release_date=movie["Release_date"],
                                  Album_ID=movie["Album_ID"]))
        return m

    @spyne.srpc(_returns=Array(MovieAlbum))
    def getMoviesAlbumsSoap():
        m = []
        for movie in movies:
            try:
                r = requests.get('http://web1:81/albums/' + movie['Album_ID'])
                r = json.loads(r.text)
                album = r[0]
                m.append(
                    MovieAlbum(ID=movie["ID"],
                               Title=movie["Title"],
                               Genre=movie["Genre"],
                               Rating=movie["Rating"],
                               Release_date=movie["Release_date"],
                               Album_ID=Album(ID=album["ID"],
                                              Album=album["Album"],
                                              Artist=album["Artist"],
                                              Genre=album["Genre"],
                                              Producer=album["Producer"])))
            except:
                m.append(
                    MovieAlbum(ID=movie["ID"],
                               Title=movie["Title"],
                               Genre=movie["Genre"],
                               Rating=movie["Rating"],
                               Release_date=movie["Release_date"],
                               Album_ID="null"))
        return m

    @spyne.srpc(Unicode, Unicode, Unicode, Unicode, Unicode, _returns=Movie)
    def newMovieSoap(Title, Genre, Rating, Release_date, Album_ID):
        numberOfMovies = len(movies)
        r = requests.get('http://web1:81/albums/' + Album_ID)
        if r.status_code == 200:
            new_Movie = {
                'ID': str(numberOfMovies),
                'Title': Title,
                'Release_date': Release_date,
                'Rating': Rating,
                'Genre': Genre,
                'Album_ID': Album_ID
            }
            movies.append(new_Movie)
            movie = movies[len(movies) - 1]
        else:
            new_Movie = {
                'ID': str(numberOfMovies),
                'Title': Title,
                'Release_date': Release_date,
                'Rating': Rating,
                'Genre': Genre,
                'Album_ID': "null"
            }
            movies.append(new_Movie)
            movie = movies[len(movies) - 1]
        return Movie(ID=movie["ID"],
                     Title=movie["Title"],
                     Genre=movie["Genre"],
                     Rating=movie["Rating"],
                     Release_date=movie["Release_date"],
                     Album_ID=movie["Album_ID"])

    @spyne.srpc(Unicode,
                Unicode,
                Unicode,
                Unicode,
                Unicode,
                Unicode,
                Unicode,
                Unicode(default=''),
                _returns=Movie)
    def newMovieAlbumSoap(Title, Genre, Rating, Release_date, Album, Artist,
                          AlbumGenre, Producer):
        if Producer != "":
            try:
                r = requests.post('http://web1:81/albums',
                                  json={
                                      "Album": Album,
                                      "Artist": Artist,
                                      "Genre": AlbumGenre,
                                      "Producer": Producer
                                  })
                r = json.loads(r.text)
                numberOfMovies = len(movies)
                new_Movie = {
                    'ID': str(numberOfMovies),
                    'Title': Title,
                    'Release_date': Release_date,
                    'Rating': Rating,
                    'Genre': Genre,
                    'Album_ID': r.get("ID")
                }
                movies.append(new_Movie)
                movie = movies[len(movies) - 1]
                return Movie(ID=movie["ID"],
                             Title=movie["Title"],
                             Genre=movie["Genre"],
                             Rating=movie["Rating"],
                             Release_date=movie["Release_date"],
                             Album_ID=r.get("ID"))
            except:
                raise Fault(faultcode='Client',
                            faultstring='',
                            faultactor='',
                            detail={
                                'Message':
                                'Error. Service Albums is not available.'
                            })

    @spyne.srpc(Unicode, Unicode, _returns=Movie)
    def rateMovieSoap(Id, Rating):
        if (re.search('^[0-9](\.[0-9]*)?$', Rating)):
            for movie in movies:
                if (movie["ID"] == Id):
                    movie["Rating"] = Rating
                    return Movie(ID=movie["ID"],
                                 Title=movie["Title"],
                                 Genre=movie["Genre"],
                                 Rating=movie["Rating"],
                                 Release_date=movie["Release_date"],
                                 Album_ID=movie["Album_ID"])

    @spyne.srpc(Unicode,
                Unicode,
                Unicode,
                Unicode,
                Unicode,
                Unicode,
                _returns=Movie)
    def changeMovieSoap(Id, Title, Genre, Release_date, Rating, Album_ID):
        try:
            r = requests.get('http://web1:81/albums/' + Album_ID)
            if r.status_code == 200 and re.search('^[0-9]?$', Id):
                movies[int(Id)]['Title'] = Title
                movies[int(Id)]['Genre'] = Genre
                movies[int(Id)]['Rating'] = Rating
                movies[int(Id)]['Release_date'] = Release_date
                movies[int(Id)]['Album_ID'] = Album_ID
                movie = movies[int(Id)]
            else:
                raise Fault(faultcode='Client',
                            faultstring='',
                            faultactor='',
                            detail={
                                'Message':
                                'Error. Service Albums status is not 200.'
                            })
            return Movie(ID=movie["ID"],
                         Title=movie["Title"],
                         Genre=movie["Genre"],
                         Rating=movie["Rating"],
                         Release_date=movie["Release_date"],
                         Album_ID=movie["Album_ID"])
        except:
            raise Fault(
                faultcode='Client',
                faultstring='',
                faultactor='',
                detail={'Message': 'Error. Service Albums is not available.'})

    @spyne.srpc(Unicode,
                Unicode,
                Unicode,
                Unicode,
                Unicode,
                Unicode,
                _returns=Movie)
    def deleteMovieSoap(Id, Title, Genre, Release_date, Rating, Album_ID):
        deleted = [movie for movie in movies if (movie['ID'] == Id)]
        if len(deleted) != 0:
            movies.remove(deleted[0])
            movie = deleted[0]
        return Movie(ID=movie["ID"],
                     Title=movie["Title"],
                     Genre=movie["Genre"],
                     Rating=movie["Rating"],
                     Release_date=movie["Release_date"],
                     Album_ID=movie["Album_ID"])

    @spyne.srpc(Unicode,
                Unicode,
                Unicode,
                Unicode,
                Unicode,
                Unicode,
                Unicode,
                Unicode,
                Unicode(default=''),
                _returns=Movie)
    def changeMovieAlbumSoap(Id, Title, Genre, Release_date, Rating, Album,
                             AlbumGenre, Producer, Artist):
        if Artist != '':
            try:
                for i in range(0, len(movies)):
                    if movies[i]["ID"] == Id:
                        r = requests.put('http://web1:81/albums/' +
                                         movies[i]["Album_ID"],
                                         json={
                                             "Album": Album,
                                             "Artist": Artist,
                                             "Genre": AlbumGenre,
                                             "Producer": Producer
                                         })
                        if r.status_code == 200 and re.search('^[0-9]?$', Id):
                            movies[i]['Title'] = Title
                            movies[i]['Genre'] = Genre
                            movies[i]['Rating'] = Rating
                            movies[i]['Release_date'] = Release_date
                            movie = movies[i]
                        else:
                            raise Fault(
                                faultcode='Client',
                                faultstring='',
                                faultactor='',
                                detail={
                                    'Message':
                                    'Error. Service Albums status is not 200.'
                                })
                return Movie(ID=movie["ID"],
                             Title=movie["Title"],
                             Genre=movie["Genre"],
                             Rating=movie["Rating"],
                             Release_date=movie["Release_date"],
                             Album_ID=movie["Album_ID"])
            except:
                raise Fault(faultcode='Client',
                            faultstring='',
                            faultactor='',
                            detail={
                                'Message':
                                'Error. Service Albums is not available.'
                            })
Ejemplo n.º 2
0
class NetworkService(HydraService):
    """
        The network SOAP service.
    """
    @rpc(Network, Unicode(pattern="[YN]", default='Y'), _returns=Network)
    def add_network(ctx, net, return_summary):
        """
        Takes an entire network complex model and saves it to the DB.  This
        complex model includes links & scenarios (with resource data).  Returns
        the network's complex model.

        As links connect two nodes using the node_ids, if the nodes are new
        they will not yet have node_ids. In this case, use negative ids as
        temporary IDS until the node has been given an permanent ID.

        All inter-object referencing of new objects should be done using
        negative IDs in the client.

        The returned object will have positive IDS

        Args:
            net (hydra_complexmodels.Network): The entire network complex model structure including nodes, links, scenarios and data

        Returns:
            hydra_complexmodels.Network: The full network structure, with correct IDs for all resources

        """
        net = network.add_network(net, **ctx.in_header.__dict__)
        ret_net = Network(net, summary=return_summary == 'Y')
        return ret_net

    @rpc(Integer,
         Unicode(pattern="[YN]", default='Y'),
         Unicode(pattern="[YN]", default='N'),
         Unicode(pattern="[YN]", default='Y'),
         Integer,
         SpyneArray(Integer()),
         _returns=Network)
    def get_network(ctx, network_id, include_resources, summary, include_data,
                    template_id, scenario_ids):
        """
        Return a whole network as a complex model.

        Args:
            network_id   (int)              : The ID of the network to retrieve
            include_resources      (char) ('Y' or 'N'): Optional flag to indicate whether resources are included with the network.
            summary      (char) ('Y' or 'N'): Optional flag to indicate whether attributes are returned with the nodes & links. Setting to 'Y' has significant speed improvements at the cost of not retrieving attribute information.
            include_data (char) ('Y' or 'N'): Optional flag to indicate whether to return datasets with the network. Defaults to 'Y', but using 'N' is much faster.
            template_id  (int)              : Optional parameter which will only return attributes on the resources that are in this template.
            scenario_ids (List(int))        : Optional parameter to indicate which scenarios to return with the network. If left unspecified, all scenarios are returned

        Returns:
            hydra_complexmodels.Network: A network complex model

        Raises:
            ResourceNotFoundError: If the network is not found.
        """
        include_resources = True if include_resources == 'Y' else False
        summary = True if summary == 'Y' else False
        net = network.get_network(network_id, include_resources, summary,
                                  include_data, scenario_ids, template_id,
                                  **ctx.in_header.__dict__)
        ret_net = Network(net, summary)
        return ret_net

    @rpc(Integer, _returns=Unicode)
    def get_network_as_json(ctx, network_id):
        """
        Return a whole network as a json string. Used for testing.

        Args:
            network_id (int): The ID of the network to retrieve

        Returns:
            string: A json-encoded representation of the network

        """
        net = network.get_network(network_id, False, 'Y', [], None,
                                  **ctx.in_header.__dict__)

        return json.dumps(str(net))

    @rpc(Integer, Unicode, _returns=Network)
    def get_network_by_name(ctx, project_id, network_name):
        """
        Search for a network by its name and return it.

        Args:
            project_id (int): As network names are only unique within a project, search for the network within the specified project
            network_name (string): The name of the network

        Returns:
            hydra_complexmodels.Network: The entire network structure, no filtering is performed, so all data and attributes are returned

        Raises:
            ResourceNotFoundError: If the project or network is not found
        """

        net = network.get_network_by_name(project_id, network_name,
                                          **ctx.in_header.__dict__)

        return Network(net)

    @rpc(Integer, Unicode, _returns=Unicode)
    def network_exists(ctx, project_id, network_name):
        """
        Using a network's name, check if a network exists or not within a project.

        Args:
            project_id (int): The project in which you are searching
            network_name (string): The name of the network you are searching for

        Returns:
           Unicode: 'Y' or 'N'

        Raises:
            ResourceNotFoundError: If the project is not defined
        """

        net_exists = network.network_exists(project_id, network_name,
                                            **ctx.in_header.__dict__)

        return net_exists

    @rpc(Network,
         Unicode(pattern="['YN']", default='Y'),
         Unicode(pattern="['YN']", default='Y'),
         Unicode(pattern="['YN']", default='Y'),
         Unicode(pattern="['YN']", default='Y'),
         _returns=Network)
    def update_network(ctx, net, update_nodes, update_links, update_groups,
                       update_scenarios):
        """
        Update an entire network.
        Send a network complex model with updated nodes, links, groups or scenarios. Using
        flags, tell the function which of these to update.

        Args:
            net (hydra_complexmodels.Network): A network reflecting an already existing network (must have an ID), which is to be updated
            updated_nodes (char) (Y or N): Flag to indicated whether the incoming network's nodes should be updated
            updated_links (char) (Y or N): Flag to indicated whether the incoming network's links should be updated
            updated_groups (char) (Y or N): Flag to indicated whether the incoming network's resource groups should be updated
            updated_scenarios (char) (Y or N): Flag to indicated whether the incoming network's data should be updated

        Returns:
            hydra_complexmodels.Network: The updated network, in summarised forms (without data or attributes)

        Raises:
            ResourceNotFoundError: If the network does not exist.


        """
        upd_nodes = True if update_nodes == 'Y' else False
        upd_links = True if update_links == 'Y' else False
        upd_groups = True if update_groups == 'Y' else False
        upd_scenarios = True if update_scenarios == 'Y' else False

        net = network.update_network(net, upd_nodes, upd_links, upd_groups,
                                     upd_scenarios, **ctx.in_header.__dict__)
        return Network(net, summary=True)

    @rpc(Integer, Integer(min_occurs=0), _returns=Node)
    def get_node(ctx, node_id, scenario_id):
        """
        Get a node using the node_id.
        optionally, scenario_id can be included if data is to be included

        Args:
            node_id (int): The node to retrieve
            scenario_id (int) (optional): Include this if you want to include data with the scenario

        Returns:
            hydra_complexmodels.Node: A node complex model, with attributes and data if requested)

        Raises:
            ResourceNotFoundError: If the node or scenario is not found

        """
        node = network.get_node(node_id, **ctx.in_header.__dict__)

        if scenario_id is not None:
            ret_node = Node(node)

            res_scens = scenario.get_resource_data('NODE', node_id,
                                                   scenario_id, None)

            rs_dict = {}
            for rs in res_scens:
                rs_dict[rs.resource_attr_id] = rs

            for ra in ret_node.attributes:
                if rs_dict.get(ra.id):
                    ra.resourcescenario = ResourceScenario(rs_dict[ra.id])

            return ret_node
        else:
            ret_node = Node(node)
            return ret_node

    @rpc(Integer, Integer, _returns=Link)
    def get_link(ctx, link_id, scenario_id):
        """
        Get a link using the link_id.
        optionally, scenario_id can be included if data is to be included

        Args:
            link_id (int): The link to retrieve
            scenario_id (int) (optional): Include this if you want to include data with the scenario

        Returns:
            hydra_complexmodels.Link: A link complex model, with attributes and data if requested)

        Raises:
            ResourceNotFoundError: If the link or scenario is not found

        """
        link = network.get_link(link_id, **ctx.in_header.__dict__)

        if scenario_id is not None:
            ret_link = Link(link)
            res_scens = scenario.get_resource_data('LINK', link_id,
                                                   scenario_id, None)
            rs_dict = {}
            for rs in res_scens:
                rs_dict[rs.resource_attr_id] = rs

            for ra in ret_link.attributes:
                if rs_dict.get(ra.id):
                    ra.resourcescenario = ResourceScenario(rs_dict[ra.id])

            return ret_link
        else:
            ret_link = Link(link)
            return ret_link

    @rpc(Integer(min_occurs=1, max_occurs="unbounded"),
         Integer(min_occurs=0),
         _returns=SpyneArray(Node))
    def get_nodes(ctx, node_ids, scenario_id):
        """
        Get nodes using the node_ids.
        optionally, scenario_id can be included if data is to be included

        Args:
            node_id (int): The node to retrieve
            scenario_id (int) (optional): Include this if you want to include data with the scenario

        Returns:
            hydra_complexmodels.Node: A node complex model, with attributes and data if requested)

        Raises:
            ResourceNotFoundError: If the node or scenario is not found

        """
        nodes = network.get_nodes(node_ids, **ctx.in_header.__dict__)
        ret_nodes = []
        if scenario_id is not None:
            for node in nodes:
                ret_node = Node(node)

                res_scens = scenario.get_resource_data('NODE', node.node_id,
                                                       scenario_id, None)

                rs_dict = {}
                for rs in res_scens:
                    rs_dict[rs.resource_attr_id] = rs

                for ra in ret_node.attributes:
                    if rs_dict.get(ra.id):
                        ra.resourcescenario = ResourceScenario(rs_dict[ra.id])
                ret_nodes.append(ret_node)

        else:
            ret_nodes = [Node(node) for node in nodes]

        return ret_nodes

    @rpc(Integer(min_occurs=1, max_occurs="unbounded"),
         Integer(min_occurs=0),
         _returns=SpyneArray(Link))
    def get_links(ctx, link_ids, scenario_id):
        """
        Get links using the link_ids.
        optionally, scenario_id can be included if data is to be included

        Args:
            link_id (int): The link to retrieve
            scenario_id (int) (optional): Include this if you want to include data with the scenario

        Returns:
            hydra_complexmodels.Link: A link complex model, with attributes and data if requested)

        Raises:
            ResourceNotFoundError: If the link or scenario is not found

        """
        links = network.get_links(link_ids, **ctx.in_header.__dict__)
        ret_links = []
        if scenario_id is not None:
            for link in links:
                ret_link = Link(link)

                res_scens = scenario.get_resource_data('LINK', link.link_id,
                                                       scenario_id, None)

                rs_dict = {}
                for rs in res_scens:
                    rs_dict[rs.resource_attr_id] = rs

                for ra in ret_link.attributes:
                    if rs_dict.get(ra.id):
                        ra.resourcescenario = ResourceScenario(rs_dict[ra.id])
                ret_links.append(ret_link)

        else:
            ret_links = [Link(link) for link in links]

        return ret_links

    @rpc(Integer, Integer, _returns=ResourceGroup)
    def get_resourcegroup(ctx, group_id, scenario_id):
        """
        Get a resourcegroup using the group_id.
        optionally, scenario_id can be included if data is to be included

        Args:
            group_id (int): The resource group to retrieve
            scenario_id (int) (optional): Include this if you want to include data with the scenario

        Returns:
            hydra_complexmodels.ResourceGroup: A resource group complex model, with attributes and data if requested)

        Raises:
            ResourceNotFoundError: If the group or scenario is not found

        """
        group = network.get_resourcegroup(group_id, **ctx.in_header.__dict__)

        if scenario_id is not None:
            ret_group = ResourceGroup(group)
            res_scens = scenario.get_resource_data('GROUP', group_id,
                                                   scenario_id, None)
            rs_dict = {}
            for rs in res_scens:
                rs_dict[rs.resource_attr_id] = rs

            for ra in ret_group.attributes:
                if rs_dict.get(ra.id):
                    ra.resourcescenario = ResourceScenario(rs_dict[ra.id])

            return ret_group
        else:
            ret_group = ResourceGroup(group)
            return ret_group

    @rpc(Integer, _returns=Unicode)
    def delete_network(ctx, network_id):
        """
        Set status of network to 'X' so it will no longer appear when you retrieve its project.
        This will not delete the network from the DB. For that use purge_network

        Args:
            network_id (int): The network to delete

        Returns:
            string: 'OK'

        Raises:
            ResourceNotFoundError: If the network is not found
        """
        #check_perm('delete_network')
        network.set_network_status(network_id, 'X', **ctx.in_header.__dict__)
        return 'OK'

    @rpc(Integer, Unicode(pattern="[YN]", default='Y'), _returns=Unicode)
    def purge_network(ctx, network_id, purge_data):
        """
        Remove a network from hydra platform completely.

        Args:
            network_id (int): The network to remove completely
            purge_data (string) ('Y' or 'N'): Any data left unconnected can be left in the DB or deleted with this flag.

        Returns:
            string: 'OK'

        Raises:
            ResourceNotFoundError: If the network is not found
        """
        #check_perm('delete_network')
        network.purge_network(network_id, purge_data, **ctx.in_header.__dict__)
        return 'OK'

    @rpc(Integer, _returns=Unicode)
    def activate_network(ctx, network_id):
        """
        Un-Deletes a network. (Set the status to 'Y' meaning it'll be included
        when you request a project's networks.

        Args:
            network_id (int): The network to reactivate

        Returns:
            string: 'OK'

        Raises:
            ResourceNotFoundError: If the network is not found.
        """
        #check_perm('delete_network')
        network.set_network_status(network_id, 'A', **ctx.in_header.__dict__)
        return 'OK'

    @rpc(Integer, _returns=NetworkExtents)
    def get_network_extents(ctx, network_id):
        """
        Given a network, return its maximum extents.
        This would be the minimum x value of all nodes,
        the minimum y value of all nodes,
        the maximum x value of all nodes and
        maximum y value of all nodes.

        Args:
            network_id (int): The network to get the extents for

        Returns:
            NetworkExtents: the min x, max x, min y, max y of all nodes in the network

        Raises:
            ResourceNotFoundError: If the network is not found.

        """
        extents = network.get_network_extents(network_id,
                                              **ctx.in_header.__dict__)

        ne = NetworkExtents()
        ne.network_id = extents['network_id']
        ne.min_x = extents['min_x']
        ne.max_x = extents['max_x']
        ne.min_y = extents['min_y']
        ne.max_y = extents['max_y']

        return ne

    @rpc(Integer, Node, _returns=Node)
    def add_node(ctx, network_id, node):
        """
        Add a node to a network:

        .. code-block:: python

            (Node){
               id = 1027
               name = "Node 1"
               description = "Node Description"
               x = 0.0
               y = 0.0
               attributes =
                  (ResourceAttrArray){
                     ResourceAttr[] =
                        (ResourceAttr){
                           attr_id = 1234
                        },
                        (ResourceAttr){
                           attr_id = 4321
                        },
                  }
             }

        Args:
            network_id (int):  The id of the network to receive the new node
            node       (hydra_complexmodels.Node): The node to be added (see above for the format)

        Returns:
            hydra_complexmodels.Node: The newly added node, complete with an ID

        Raises:
            ResourceNotFoundError: If the network is not found
        """

        node_dict = network.add_node(network_id, node,
                                     **ctx.in_header.__dict__)

        new_node = Node(node_dict)

        return new_node

    @rpc(Integer, SpyneArray(Node), _returns=SpyneArray(Node))
    def add_nodes(ctx, network_id, nodes):
        """
        Add a lost of nodes to a network

        Args:
            network_id (int):  The id of the network to receive the new node
            node       (List(hydra_complexmodels.Node)): A list of the nodes to be added

        Returns:
            List(hydra_complexmodels.Node): The newly added nodes, each complete with an ID

        Raises:
            ResourceNotFoundError: If the network is not found
        """

        node_s = network.add_nodes(network_id, nodes, **ctx.in_header.__dict__)
        new_nodes = []
        for node in nodes:
            for node_ in node_s:
                if (node.name == node_.node_name):
                    new_nodes.append(Node(node_, summary=True))
                    break

        return new_nodes

    @rpc(Integer, SpyneArray(Link), _returns=SpyneArray(Link))
    def add_links(ctx, network_id, links):
        """
        Add a lost of links to a network

        Args:
            network_id (int):  The id of the network to receive the new link
            link       (List(hydra_complexmodels.Link)): A list of the links to be added

        Returns:
            List(hydra_complexmodels.Link): The newly added links, each complete with an ID

        Raises:
            ResourceNotFoundError: If the network is not found

        """
        link_s = network.add_links(network_id, links, **ctx.in_header.__dict__)

        new_links = []
        for link in links:
            for link_ in link_s:
                if (link.name == link_.link_name):
                    new_links.append(Link(link_, summary=True))
                    break

        return new_links

    @rpc(Node, _returns=Node)
    def update_node(ctx, node):
        """
        Update a node.
        If new attributes are present, they will be added to the node.
        The non-presence of attributes does not remove them.

        .. code-block:: python

            (Node){
               id = 1039
               name = "Node 1"
               description = "Node Description"
               x = 0.0
               y = 0.0
               status = "A"
               attributes =
                  (ResourceAttrArray){
                     ResourceAttr[] =
                        (ResourceAttr){
                           id = 850
                           attr_id = 1038
                           ref_id = 1039
                           ref_key = "NODE"
                           attr_is_var = True
                        },
                        (ResourceAttr){
                           id = 852
                           attr_id = 1040
                           ref_id = 1039
                           ref_key = "NODE"
                           attr_is_var = True
                        },
                  }
             }

        Args:
            node (hydra_complexmodels.Node): The node to be updated

        Returns:
            hydra_complexmodels.Node: The updated node.

        Raises:
            ResourceNotFoundError: If the node is not found
        """

        node_dict = network.update_node(node, **ctx.in_header.__dict__)
        updated_node = Node(node_dict)

        return updated_node

    @rpc(Integer, _returns=Unicode)
    def delete_node(ctx, node_id):
        """
        Set status of node to 'X' so it will no longer appear when you retrieve its network.
        This will not delete the node from the DB. For that use purge_node

        Args:
            node_id (int): The node to delete

        Returns:
            string: 'OK'

        Raises:
            ResourceNotFoundError: If the node is not found
        """
        #check_perm('edit_topology')
        network.set_node_status(node_id, 'X', **ctx.in_header.__dict__)
        return 'OK'

    @rpc(Integer, _returns=Unicode)
    def activate_node(ctx, node_id):
        """
        Set the status of a node to 'A'

        Un-Deletes a node. (Set the status to 'Y' meaning it'll be included
        when you request a network.

        Args:
            node_id (int): The node to reactivate

        Returns:
            string: 'OK'

        Raises:
            ResourceNotFoundError: If the node is not found.
        """
        #check_perm('edit_topology')
        network.set_node_status(node_id, 'A', **ctx.in_header.__dict__)
        return 'OK'

    @rpc(Integer, Unicode(pattern="[YN]", default='Y'), _returns=Unicode)
    def purge_node(ctx, node_id, purge_data):
        """
            Remove node from DB completely
            If there are attributes on the node, use purge_data to try to
            delete the data. If no other resources link to this data, it
            will be deleted.

        Args:
            node_id (int): The node to remove completely
            purge_data (string) ('Y' or 'N'): Any data left unconnected can be left in the DB or deleted with this flag.

        Returns:
            string: 'OK'

        Raises:
            ResourceNotFoundError: If the node is not found
        """
        network.delete_node(node_id, purge_data, **ctx.in_header.__dict__)
        return 'OK'

    @rpc(Integer, Link, _returns=Link)
    def add_link(ctx, network_id, link):
        """
        Add a link to a network

        Args:
            network_id (int):  The id of the network to receive the new link
            link       (hydra_complexmodels.Link): The link to be added (see above for the format)

        Returns:
            hydra_complexmodels.Link: The newly added link, complete with an ID

        Raises:
            ResourceNotFoundError: If the network is not found
        """

        link_dict = network.add_link(network_id, link,
                                     **ctx.in_header.__dict__)
        new_link = Link(link_dict)

        return new_link

    @rpc(Link, _returns=Link)
    def update_link(ctx, link):
        """
        Update a link.

        Args:
            link       (hydra_complexmodels.Link): The link to be updated

        Returns:
            hydra_complexmodels.Link: The updated link.

        Raises:
            ResourceNotFoundError: If the link is not found
        """
        link_dict = network.update_link(link, **ctx.in_header.__dict__)
        updated_link = Link(link_dict)

        return updated_link

    @rpc(Integer, _returns=Unicode)
    def delete_link(ctx, link_id):
        """
        Set the status of a link to 'X'

        Args:
            link_id (int): The link to delete

        Returns:
            string: 'OK'

        Raises:
            ResourceNotFoundError: If the link is not found

        """
        network.set_link_status(link_id, 'X', **ctx.in_header.__dict__)
        return 'OK'

    @rpc(Integer, _returns=Unicode)
    def activate_link(ctx, link_id):
        """
        Set the status of a link to 'A'

        Args:
            link_id (int): The link to reactivate

        Returns:
            string: 'OK'

        Raises:
            ResourceNotFoundError: If the link is not found.

        """
        network.set_link_status(link_id, 'A', **ctx.in_header.__dict__)
        return 'OK'

    @rpc(Integer, Unicode(pattern="[YN]", default='Y'), _returns=Unicode)
    def purge_link(ctx, link_id, purge_data):
        """
        Remove link from DB completely
        If there are attributes on the link, use purge_data to try to
        delete the data. If no other resources link to this data, it
        will be deleted.

        Args:
            link_id (int): The link to reactivate

        Returns:
            string: 'OK'

        Raises:
            ResourceNotFoundError: If the link is not found.
        """
        network.delete_link(link_id, purge_data, **ctx.in_header.__dict__)
        return 'OK'

    @rpc(Integer, ResourceGroup, _returns=ResourceGroup)
    def add_group(ctx, network_id, group):
        """
        Add a resourcegroup to a network

        Args:
            network_id (int):  The id of the network to receive the new node
            group      (hydra_complexmodels.ResourceGroup): The group to be added

        Returns:
            hydra_complexmodels.ResourceGroup: The newly added group, complete with an ID

        Raises:
            ResourceNotFoundError: If the network is not found
        """

        group_i = network.add_group(network_id, group,
                                    **ctx.in_header.__dict__)
        new_group = ResourceGroup(group_i)

        return new_group

    @rpc(Integer, _returns=Unicode)
    def delete_group(ctx, group_id):
        """
        Set the status of a group to 'X'
        Args:
            group_id (int): The resource group to delete

        Returns:
            string: 'OK'

        Raises:
            ResourceNotFoundError: If the resource group is not found

        """
        network.set_group_status(group_id, 'X', **ctx.in_header.__dict__)
        return 'OK'

    @rpc(Integer, Unicode(pattern="[YN]", default='Y'), _returns=Unicode)
    def purge_group(ctx, group_id, purge_data):
        """
        Remove a resource group from the DB completely. If purge data is set
        to 'Y', any data that is unconnected after the removal of the group
        will be removed also.

        Args:
            group_id (int): The resource group to remove completely
            purge_data (string) ('Y' or 'N'): Any data left unconnected can be left in the DB or deleted with this flag.

        Returns:
            string: 'OK'

        Raises:
            ResourceNotFoundError: If the resource group is not found

        """
        network.delete_group(group_id, purge_data, **ctx.in_header.__dict__)
        return 'OK'

    @rpc(Integer, _returns=Unicode)
    def activate_group(ctx, group_id):
        """
        Set the status of a group to 'A'

        Args:
            group_id (int): The resource group to reactivate

        Returns:
            string: 'OK'

        Raises:
            ResourceNotFoundError: If the resource group is not found.

        """
        network.set_group_status(group_id, 'A', **ctx.in_header.__dict__)
        return 'OK'

    @rpc(Integer, _returns=SpyneArray(Scenario))
    def get_scenarios(ctx, network_id):
        """
        Get all the scenarios in a given network.

        Args:
            network_id (int): The network from which to retrieve the scenarios

        Returns:
            List(hydra_complexmodels.Scenario): All the scenarios in the network

        Raises:
            ResourceNotFoundError: If the network is not found
        """
        scenarios_i = network.get_scenarios(network_id,
                                            **ctx.in_header.__dict__)

        scenarios = [Scenario(scen) for scen in scenarios_i]

        return scenarios

    @rpc(Integer, _returns=SpyneArray(Integer))
    def validate_network_topology(ctx, network_id):
        """
        Check for the presence of orphan nodes in a network.
        Args:
            network_id (int): The network to check

        Returns:
            List(int)): IDs of all the orphan nodes in the network

        Raises:
            ResourceNotFoundError: If the network is not found

        """
        return network.validate_network_topology(network_id,
                                                 **ctx.in_header.__dict__)

    @rpc(Integer,
         Integer(min_occurs=1, max_occurs="unbounded"),
         _returns=SpyneArray(ResourceSummary))
    def get_resources_of_type(ctx, network_id, type_id):
        """
        Return a list of Nodes, Links or ResourceGroups
        which have the specified type.

        Args:
            network_id (int): Types of resources in this network
            type_id    (int): Search for resources of this type.

        Returns:
            List(ResourceSummary): These objects contain the attributes common to all resources, namely: type, id, name, description, attribues and types.

        Raises:
            ResourceNotFoundError: If the network or type is not found
        """

        if type(type_id) == int:
            type_id = [type_id]

        nodes, links, networks, groups = network.get_resources_of_type(
            network_id, type_id, **ctx.in_header.__dict__)

        resources = []
        for n in nodes:
            resources.append(ResourceSummary(n))
        for l in links:
            resources.append(ResourceSummary(l))
        for n in networks:
            resources.append(ResourceSummary(n))
        for g in groups:
            resources.append(ResourceSummary(g))

        return resources

    @rpc(Integer, _returns=Unicode)
    def clean_up_network(ctx, network_id):
        """
        Purge all nodes, links, groups and scenarios from a network which
        have previously been deleted.

        Args:
            network_id (int): The network to clean up

        Returns:
            string: 'OK'

        Raises:
            ResourceNotFoundError: If the network is not found

        """
        return network.clean_up_network(network_id, **ctx.in_header.__dict__)

    @rpc(Integer,
         Integer,
         Integer(max_occurs="unbounded"),
         Unicode(pattern="['YN']", default='N'),
         _returns=SpyneArray(ResourceAttr))
    def get_all_node_data(ctx, network_id, scenario_id, node_ids,
                          include_metadata):
        """
        Return all the attributes for all the nodes in a given network and a
        given scenario.


        Args:
            network_id (int): The network to search in
            scenario_id (int): The scenario to search
            node_ids (List(int)) (optional): The specific nodes to search for data in. If not specified, all the nodes in the network will be searched.
            include_metadata: (string) ('Y' or 'N'): Default 'N'. Set to 'Y' to return metadata. This may vause a performance hit as metadata is BIG!

        Returns:
            List(ResourceAttr), each with a resourcescenario attribute, containing the actual value for the scenario specified.

        Raises:
            ResourceNotFoundError: If the network or scenario are not found

        """
        start = datetime.datetime.now()

        node_resourcescenarios = network.get_attributes_for_resource(
            network_id, scenario_id, 'NODE', node_ids, include_metadata)

        log.info("Qry done in %s", (datetime.datetime.now() - start))
        start = datetime.datetime.now()

        return_ras = []
        for ns in node_resourcescenarios:
            ra = ResourceAttr(ns.resourceattr)
            x = ResourceScenario(ns, ra.attr_id)
            ra.resourcescenario = x
            return_ras.append(ra)

        log.info("Return vals built in %s", (datetime.datetime.now() - start))

        return return_ras

    @rpc(Integer,
         Unicode(pattern="['YN']", default='N'),
         Unicode(pattern="['YN']", default='N'),
         Integer(min_occurs=0, max_occurs=1),
         Integer(min_occurs=0, max_occurs=1),
         _returns=SpyneArray(ResourceData))
    def get_all_resource_data(ctx, scenario_id, include_values,
                              include_metadata, page_start, page_end):
        """
        Return all the attributes for all the nodes in a given network and a
        given scenario.

        In this function array data and timeseries data are returned as JSON strings.

        If your data structure looks like:

        +----+----+-----+
        | H1 | H2 | H3  |
        +====+====+=====+
        | 1  | 10 | 100 |
        +----+----+-----+
        | 2  | 20 | 200 |
        +----+----+-----+
        | 3  | 30 | 300 |
        +----+----+-----+
        | 4  | 40 | 400 |
        +----+----+-----+

        Then hydra will provide the data in the following format:

        '{
            "H1" : {"0":1, "1":2, "3":3, "4":4},\n
            "H2"  : {"0":10, "1":20, "3":30, "4":40},\n
            "H3"  : {"0":100, "1":200, "3":300, "4":400}\n
        }'

        For a timeseries:

        +-------------------------+----+----+-----+
        | Time                    | H1 | H2 | H3  |
        +=========================+====+====+=====+
        | 2014/09/04 16:46:12:00  | 1  | 10 | 100 |
        +-------------------------+----+----+-----+
        | 2014/09/05 16:46:12:00  | 2  | 20 | 200 |
        +-------------------------+----+----+-----+
        | 2014/09/06 16:46:12:00  | 3  | 30 | 300 |
        +-------------------------+----+----+-----+
        | 2014/09/07 16:46:12:00  | 4  | 40 | 400 |
        +-------------------------+----+----+-----+

        Then hydra will provide the data in the following format:

        '{
            "H1" : {\n
                    "2014/09/04 16:46:12:00":1,\n
                    "2014/09/05 16:46:12:00":2,\n
                    "2014/09/06 16:46:12:00":3,\n
                    "2014/09/07 16:46:12:00":4},\n

            "H2" : {\n
                    "2014/09/04 16:46:12:00":10,\n
                    "2014/09/05 16:46:12:00":20,\n
                    "2014/09/06 16:46:12:00":30,\n
                    "2014/09/07 16:46:12:00":40},\n

            "H3" :  {\n
                     "2014/09/04 16:46:12:00":100,\n
                     "2014/09/05 16:46:12:00":200,\n
                     "2014/09/06 16:46:12:00":300,\n
                     "2014/09/07 16:46:12:00":400}\n
        }'


        Args:
            scenario_id (int): The scenario to search
            include_values (string) ('Y' or 'N'): Default 'N'. Set to 'Y' to return the values. This may vause a performance hit as values are BIG!
            include_metadata: (string) ('Y' or 'N'): Default 'N'. Set to 'Y' to return metadata. This may vause a performance hit as metadata is BIG!
            page_start (int): The start of the search results (allows you to contol the nuber of results)
            page_end (int): The end of the search results

        Returns:
            List(ResourceData): A list of objects describing datasets specifically designed for efficiency

        """
        start = datetime.datetime.now()

        log.info("Getting all resource data for scenario %s", scenario_id)
        node_resourcedata = network.get_all_resource_data(
            scenario_id,
            include_metadata=include_metadata,
            page_start=page_start,
            page_end=page_end)

        log.info("Qry done in %s", (datetime.datetime.now() - start))

        start = datetime.datetime.now()

        return_ras = []
        for nodeattr in node_resourcedata:
            ra = ResourceData(nodeattr, include_values)
            return_ras.append(ra)

        log.info("%s return data found in %s", len(return_ras),
                 (datetime.datetime.now() - start))

        return return_ras

    @rpc(Integer,
         Integer,
         Integer(max_occurs="unbounded"),
         Unicode(pattern="['YN']", default='N'),
         _returns=SpyneArray(ResourceAttr))
    def get_all_link_data(ctx, network_id, scenario_id, link_ids,
                          include_metadata):
        """
        Return all the attributes for all the links in a given network and a
        given scenario.
        Returns a list of ResourceAttr objects, each with a resourcescenario
        attribute, containing the actual value for the scenario specified.

        Args:
            network_id (int): The network to search in
            scenario_id (int): The scenario to search
            link_ids (List(int)) (optional): The specific links to search for data in. If not specified, all the links in the network will be searched.
            include_metadata: (string) ('Y' or 'N'): Default 'N'. Set to 'Y' to return metadata. This may vause a performance hit as metadata is BIG!

        Returns:
            List(ResourceAttr), each with a resourcescenario attribute, containing the actual value for the scenario specified.

        Raises:
            ResourceNotFoundError: If the network or scenario are not found


        """
        start = datetime.datetime.now()

        link_resourcescenarios = network.get_attributes_for_resource(
            network_id, scenario_id, 'LINK', link_ids, include_metadata)

        log.info("Qry done in %s", (datetime.datetime.now() - start))
        start = datetime.datetime.now()

        return_ras = []
        for linkrs in link_resourcescenarios:
            ra = ResourceAttr(linkrs.resourceattr)
            ra.resourcescenario = ResourceScenario(linkrs, ra.attr_id)
            return_ras.append(ra)

        log.info("Return vals built in %s", (datetime.datetime.now() - start))

        return return_ras

    @rpc(Integer,
         Integer,
         Integer(max_occurs="unbounded"),
         Unicode(pattern="['YN']", default='N'),
         _returns=SpyneArray(ResourceAttr))
    def get_all_group_data(ctx, network_id, scenario_id, group_ids,
                           include_metadata):
        """
        Return all the attributes for all the groups in a given network and a
        given scenario.
        Returns a list of ResourceAttr objects, each with a resourcescenario
        attribute, containing the actual value for the scenario specified.

        Args:
            network_id (int): The network to search in
            scenario_id (int): The scenario to search
            group_ids (List(int)) (optional): The specific resource groups to search for data in. If not specified, all the groups in the network will be searched.
            include_metadata: (string) ('Y' or 'N'): Default 'N'. Set to 'Y' to return metadata. This may vause a performance hit as metadata is BIG!

        Returns:
            List(ResourceAttr), each with a resourcescenario attribute, containing the actual value for the scenario specified.

        """

        group_resourcescenarios = network.get_attributes_for_resource(
            network_id, scenario_id, 'GROUP', group_ids, include_metadata)
        return_ras = []
        for grouprs in group_resourcescenarios:
            ra = ResourceAttr(grouprs.resourceattr)
            ra.resourcescenario = ResourceScenario(grouprs, ra.attr_id)
            return_ras.append(ra)

        return return_ras
Ejemplo n.º 3
0
class SharingService(HydraService):
    """
        The network SOAP service.
    """

    @rpc(Integer, Unicode(max_occurs='unbounded'),
         Unicode(pattern="[YN]"), Unicode(pattern="[YN]", default='Y'), _returns=Unicode())
    def share_network(ctx, network_id, usernames, read_only, share):
        """

        Share a network with a list of users, identified by their usernames.

        Args:
            network_id (int): The ID of the network to share
            usernames  (List(Unicode)): THe list of usernames with whom to share the network
            read_only  (string) (Y or N): Can the users edit as well as view the network?
            share      (string) (optional) (Y or N): Can the users share the network with other users? This only goes 1 level deep, so if you share a network with a user and give them sharing ability, they cannot then set the 'share' flag to 'Y' when sharing with someone else.

        Returns:
            string: 'OK'

        Raises:
            ResourceNotFoundError: If the network is not found
            ResourceNotFoundError: If one of the usernames is incorrect or does not exist

        """

        sharing.share_network(network_id,
                              usernames,
                              read_only,
                              share,
                              **ctx.in_header.__dict__)

        return 'OK'

    @rpc(Integer, Unicode(max_occurs='unbounded'),
         Unicode(pattern="[YN]"), Unicode(pattern="[YN]"), _returns=Unicode)
    def share_project(ctx, project_id, usernames, read_only, share):
        """

        Share an entire project with a list of users, identifed by their usernames.
        All the projectt's networks will be shared also.
            
        Args:
            project_id (int): The ID of the project to share
            usernames  (List(Unicode)): The list of usernames with whom to share the project
            read_only  (string) (Y or N): Can the users edit as well as view the project?
            share      (string) (optional) (Y or N): Can the users share the project with other users? This only goes 1 level deep, so if you share a project with a user and give them sharing ability, they cannot then set the 'share' flag to 'Y' when sharing with someone else.

        Returns:
            string: 'OK'

        Raises:
            ResourceNotFoundError: If the project is not found
            ResourceNotFoundError: If one of the usernames is incorrect or does not exist

        """
        sharing.share_project(project_id,
                              usernames,
                              read_only,
                              share,
                              **ctx.in_header.__dict__)
        return "OK"

    @rpc(Integer, Unicode(max_occurs="unbounded"),
         Unicode(pattern="[YN]"), Unicode(pattern="[YN]"), Unicode(pattern="[YN]"),
         _returns=Unicode)
    def set_project_permission(ctx, project_id, usernames, read, write, share):
        """

        Set permissions on a project to a list of users, identifed by their usernames. 
        THIS ACTION IS THEN PERFORMED ON ALL THE PROJECT'S NETWORKS!
            
        Args:
            project_id (int): The ID of the project to share
            usernames  (List(Unicode)): The list of usernames with whom to share the project
            read       (string) (Y or N): Can the users read the project?
            write      (string) (Y or N): Can the users edit the project?
            share      (string) (optional) (Y or N): Can the users share the project with other users? This only goes 1 level deep, so if you share a network with a user and give them sharing ability, they cannot then set the 'share' flag to 'Y' when sharing with someone else.

        Returns:
            string: 'OK'

        Raises:
            ResourceNotFoundError: If the project is not found
            ResourceNotFoundError: If one of the usernames is incorrect or does not exist

        """
        sharing.set_project_permission(project_id,
                                       usernames,
                                       read,
                                       write,
                                       share,
                                       **ctx.in_header.__dict__)

        return "OK"

    @rpc(Integer, Integer, _returns=ProjectOwner)
    def get_project_permissions(ctx, project_id, user_id):
        """

        Get permissions on a project for a specific user.

        Args:
            project_id (int): The ID of the project to share
            user_id  (int): The list of usernames with whom to share the project

        Returns:
            hydra_complexmodels.ProjectOwner: The project owner with sharing info.

        Raises:

        """
        owner = sharing.get_project_permissions(project_id, user_id)
        ret_owner = ProjectOwner(owner)
        return ret_owner

    @rpc(Integer, Unicode(max_occurs="unbounded"),
         Unicode(pattern="[YN]"), Unicode(pattern="[YN]"), Unicode(pattern="[YN]"),
         _returns=Unicode)
    def set_network_permission(ctx, network_id, usernames, read, write, share):
        """

        Set permissions on a network to a list of users, identifed by 
        their usernames. The read flag ('Y' or 'N') sets read access, the write
        flag sets write access. If the read flag is 'N', then there is
        automatically no write access or share access.

        Args:
            network_id (int): The ID of the network to share
            usernames  (List(Unicode)): The list of usernames with whom to share the network
            read       (string) (Y or N): Can the users read the network?
            write      (string) (Y or N): Can the users edit the network?
            share      (string) (optional) (Y or N): Can the users share the network with other users? This only goes 1 level deep, so if you share a network with a user and give them sharing ability, they cannot then set the 'share' flag to 'Y' when sharing with someone else.

        Returns:
            string: 'OK'

        Raises:
            ResourceNotFoundError: If the network is not found
            ResourceNotFoundError: If one of the usernames is incorrect or does not exist

        """

        sharing.set_network_permission(network_id,
                                       usernames,
                                       read,
                                       write,
                                       share,
                                       **ctx.in_header.__dict__)

        return "OK"

    @rpc(Integer, Unicode(max_occurs="unbounded"),
         Unicode(pattern="[YN]"), Unicode(pattern="[YN]"), Unicode(pattern="[YN]"),
         _returns=Unicode)
    def hide_dataset(ctx, dataset_id, exceptions, read, write, share):
        """

        Hide a particular piece of data so it can only be seen by its owner.
        Only an owner can hide (and unhide) data.
        Data with no owner cannot be hidden.
       
        Args:
            dataset_id (int): The ID of the dataset to be hidden
            exceptions  (List(Unicode)): the usernames of those with permission to view the data
            read       (string) (Y or N): Can the users read the dataset?
            write      (string) (Y or N): Can the users edit the dataset?
            share      (string) (Y or N): Can the users share the dataset with other users? This only goes 1 level deep, so if you share a network with a user and give them sharing ability, they cannot then set the 'share' flag to 'Y' when sharing with someone else.

        Returns:
            string: 'OK'

        Raises:
            ResourceNotFoundError: If the dataset is not found
            HydraError: If the request is being made by a non-owner of the dataset

        """
        sharing.hide_dataset(dataset_id,
                             exceptions,
                             read,
                             write,
                             share,
                             **ctx.in_header.__dict__)

        return "OK"

    @rpc(Integer,
         _returns=Unicode)
    def unhide_dataset(ctx, dataset_id):
        """
        Un Hide a particular piece of data so it can only be seen by its owner.
        Only an owner can hide (and unhide) data.

        Args:
            dataset_id (int): The ID of the dataset to be un-hidden 

        Returns:
            string: 'OK'

        Raises:
            ResourceNotFoundError: If the dataset is not found
            HydraError: If the request is being made by a non-owner of the dataset

        """
        sharing.unhide_dataset(dataset_id,
                               **ctx.in_header.__dict__)

        return "OK"

    @rpc(Integer, Unicode(max_occurs='unbounded'),
         Unicode(pattern="[YN]"), Unicode(pattern="[YN]"), _returns=Unicode)
    def share_template(ctx, template_id, usernames, read_only, share):
        """

        Share a template with a list of users, identifed by their usernames.

        Args:
            template_id (int): The ID of the project to share
            usernames  (List(Unicode)): The list of usernames with whom to share the project
            read_only  (string) (Y or N): Can the users edit as well as view the project?
            share      (string) (optional) (Y or N): Can the users share the project with other users? This only goes 1 level deep, so if you share a project with a user and give them sharing ability, they cannot then set the 'share' flag to 'Y' when sharing with someone else.

        Returns:
            string: 'OK'

        Raises:
            ResourceNotFoundError: If the project is not found
            ResourceNotFoundError: If one of the usernames is incorrect or does not exist

        """
        sharing.share_template(template_id,
                               usernames,
                               read_only,
                               share,
                               **ctx.in_header.__dict__)
        return "OK"

    @rpc(Integer, Unicode(max_occurs="unbounded"),
         Unicode(pattern="[YN]"), Unicode(pattern="[YN]"), Unicode(pattern="[YN]"),
         _returns=Unicode)
    def set_template_permission(ctx, template_id, usernames, read, write, share):
        """

        Set permissions on a template to a list of users, identifed by their usernames.

        Args:
            template_id (int): The ID of the template to share
            usernames  (List(Unicode)): The list of usernames with whom to share the project
            read       (string) (Y or N): Can the users read the project?
            write      (string) (Y or N): Can the users edit the project?
            share      (string) (optional) (Y or N): Can the users share the project with other users? This only goes 1 level deep, so if you share a network with a user and give them sharing ability, they cannot then set the 'share' flag to 'Y' when sharing with someone else.

        Returns:
            string: 'OK'

        Raises:
            ResourceNotFoundError: If the template is not found
            ResourceNotFoundError: If one of the usernames is incorrect or does not exist

        """
        sharing.set_template_permission(template_id,
                                       usernames,
                                       read,
                                       write,
                                       share,
                                       **ctx.in_header.__dict__)

        return "OK"
Ejemplo n.º 4
0
 def test_simple_type_explicit_customization(self):
     assert Unicode(max_len=5).__extends__ is not None
     assert Unicode.customize(max_len=5).__extends__ is not None
Ejemplo n.º 5
0
 class SomeComplexModel(ComplexModel):
     _type_info = [
         ('a', Unicode),
         ('b',
          Unicode(min_occurs=1, default='default', nillable=True)),
     ]
Ejemplo n.º 6
0
 def test_unicode_pattern_mult_cust(self):
     assert Unicode(pattern='a').Attributes.pattern == 'a'
     assert Unicode(pattern='a')(5).Attributes.pattern == 'a'
Ejemplo n.º 7
0
 def test_unicode_nullable_mult_cust_true(self):
     assert Unicode(nullable=True).Attributes.nullable == True
     assert Unicode(nullable=True)(5).Attributes.nullable == True
Ejemplo n.º 8
0
class Address(ComplexModelBase):
    addressPlace = Place
    addressStreet = Unicode(255)
    addressHouse = Unicode(255)
    addressPorch = Unicode(255)
    addressInfo = Unicode
Ejemplo n.º 9
0
class Passenger(ComplexModelBase):
    passengerName = Mandatory.Unicode(255)
    passengerPatronymic = Unicode(255)
    passengerSurname = Unicode(255)
    passengerPhone = Mandatory.Unicode(255)
    passengerDescription = Unicode
Ejemplo n.º 10
0
class AttributeService(HydraService):
    """
        The attribute SOAP service
    """
    @rpc(Attr, _returns=Attr)
    def add_attribute(ctx, attr):
        """
        Add a generic attribute, which can then be used in creating
        a resource attribute, and put into a type.

        .. code-block:: python

            (Attr){
                name = "Test Attr"
                dimen = "very big"
                description = "I am a very big attribute"
            }

        Args:
            attr (hydra_complexmodels.Attr): An attribute object, as described above.

        Returns:
            hydra_complexmodels.Attr: An attribute object, similar to the one sent in but with an ID. 
        """

        attr = attributes.add_attribute(attr, **ctx.in_header.__dict__)
        return Attr(attr)

    @rpc(Attr, _returns=Attr)
    def update_attribute(ctx, attr):
        """
        Update a generic attribute, which can then be used in creating a resource attribute, and put into a type.

        .. code-block:: python

            (Attr){
                id = 1020
                name = "Test Attr"
                dimen = "very big"
                description = "I am a very big attribute"
            }

        Args:
            attr (hydra_complexmodels.Attr): An attribute complex model, as described above.

        Returns:
            hydra_complexmodels.Attr: An attribute complex model, reflecting the one sent in. 

        """
        attr = attributes.update_attribute(attr, **ctx.in_header.__dict__)
        return Attr(attr)

    @rpc(SpyneArray(Attr), _returns=SpyneArray(Attr))
    def add_attributes(ctx, attrs):
        """
        Add multiple generic attributes

        Args:
            attrs (List[Attr]): A list of attribute complex models, 
                as described above.

        Returns:
            List[Attr]: A list of attribute complex models,
                reflecting the ones sent in. 

        """

        attrs = attributes.add_attributes(attrs, **ctx.in_header.__dict__)
        ret_attrs = [Attr(attr) for attr in attrs]
        return ret_attrs

    @rpc(_returns=SpyneArray(Attr))
    def get_all_attributes(ctx):
        """
        Get all the attributes in the system

        Args:
            None

        Returns:
            List[Attr]: A list of attribute complex models
        """

        attrs = attributes.get_attributes(**ctx.in_header.__dict__)
        ret_attrs = [Attr(attr) for attr in attrs]
        return ret_attrs

    @rpc(Integer, _returns=Attr)
    def get_attribute_by_id(ctx, ID):
        """
        Get a specific attribute by its ID.

        Args:
            ID (int): The ID of the attribute

        Returns:
            hydra_complexmodels.Attr: An attribute complex model.
                Returns None if no attribute is found.
        """
        attr = attributes.get_attribute_by_id(ID, **ctx.in_header.__dict__)

        if attr:
            return Attr(attr)

        return None

    @rpc(Unicode, Unicode, _returns=Attr)
    def get_attribute(ctx, name, dimension):
        """
        Get a specific attribute by its name and dimension (this combination
        is unique for attributes in Hydra Platform).

        Args:
            name (unicode): The name of the attribute
            dimension (unicode): The dimension of the attribute

        Returns:
            hydra_complexmodels.Attr: An attribute complex model.
                Returns None if no attribute is found.

        """
        attr = attributes.get_attribute_by_name_and_dimension(
            name, dimension, **ctx.in_header.__dict__)
        if attr:
            return Attr(attr)

        return None

    @rpc(Integer, _returns=SpyneArray(Attr))
    def get_template_attributes(ctx, template_id):
        """
            Get all the attributes in a template.
            Args

                param (int) template_id

            Returns

                List(Attr)
        """
        attrs = attributes.get_template_attributes(template_id,
                                                   **ctx.in_header.__dict__)

        return [Attr(a) for a in attrs]

    @rpc(SpyneArray(Attr), _returns=SpyneArray(Attr))
    def get_attributes(ctx, attrs):
        """
        Get a list of attribute, by their names and dimension. Takes a list
            of attribute objects, picks out their name & dimension, finds the appropriate
            attribute in the DB and updates the incoming attribute with an ID.
            The same attributes go out that came in, except this time with an ID.
            If one of the incoming attributes does not match, this attribute is not
            returned.

        Args:
            attrs (List(Attr)): A list of attribute complex models

        Returns:
            List(hydra_complexmodels.Attr): List of Attr complex models
        
        """
        ret_attrs = []
        for a in attrs:
            log.info("Getting attribute %s, %s", a.name, a.dimen)
            attr = attributes.get_attribute_by_name_and_dimension(
                a.name, a.dimen, **ctx.in_header.__dict__)
            if attr:
                a.id = attr.attr_id
                a.cr_date = str(attr.cr_date)
                a.name = attr.attr_name
                a.dimen = attr.attr_dimen
                a.description = attr.attr_description
                ret_attrs.append(a)
            else:
                ret_attrs.append(None)

        return ret_attrs

    @rpc(Integer, Unicode(pattern="['YN']"), _returns=ResourceAttr)
    def update_resource_attribute(ctx, resource_attr_id, is_var):
        """
        Update a resource attribute (which means update the is_var flag
        as this is the only thing you can update on a resource attr)

        Args:
            resource_attr_id (int): ID of the complex model to be updated
            is_var           (unicode): 'Y' or 'N'

        Returns:
            List(hydra_complexmodels.ResourceAttr): Updated ResourceAttr

        Raises:
            ResourceNotFoundError if the resource_attr_id is not in the DB
        """
        updated_ra = attributes.update_resource_attribute(
            resource_attr_id, is_var, **ctx.in_header.__dict__)
        return ResourceAttr(updated_ra)

    @rpc(Integer, _returns=Unicode)
    def delete_resourceattr(ctx, resource_attr_id):
        """
        Deletes a resource attribute and all associated data.
        ***WILL BE DEPRECATED***

        Args:
            resource_attr_id (int): ID of the complex model to be deleted 

        Returns:
            unicode: 'OK'

        Raises:
            ResourceNotFoundError if the resource_attr_id is not in the DB

        """
        attributes.delete_resource_attribute(resource_attr_id,
                                             **ctx.in_header.__dict__)

        return 'OK'

    @rpc(Integer, _returns=Unicode)
    def delete_resource_attribute(ctx, resource_attr_id):
        """
        Add a resource attribute attribute to a resource (Duplicate of delete_resourceattr)

        Args:
            resource_attr_id (int): ID of the complex model to be deleted 

        Returns:
            unicode: 'OK'

        Raises:
            ResourceNotFoundError if the resource_attr_id is not in the DB

        """
        attributes.delete_resource_attribute(resource_attr_id,
                                             **ctx.in_header.__dict__)

        return "OK"

    @rpc(Integer,
         Integer,
         Unicode(pattern="['YN']", default='N'),
         _returns=ResourceAttr)
    def add_network_attribute(ctx, network_id, attr_id, is_var):
        """
        Add a resource attribute to a network.

        Args:
            network_id (int): ID of the network 
            attr_id    (int): ID of the attribute to assign to the network
            is_var     (string) 'Y' or 'N'. Indicates whether this attribute is
                a variable or not. (a variable is typically the result of a model run,
                so therefore doesn't need data assigned to it initially)

        Returns:
            hydra_complexmodels.ResourceAttr: A complex model of the newly created resource attribute.
        Raises:
            ResourceNotFoundError: If the network or attribute are not in the DB.
            HydraError           : If the attribute is already on the network.

        """
        new_ra = attributes.add_resource_attribute('NETWORK', network_id,
                                                   attr_id, is_var,
                                                   **ctx.in_header.__dict__)

        return ResourceAttr(new_ra)

    @rpc(Integer, Integer, _returns=SpyneArray(ResourceAttr))
    def add_network_attrs_from_type(ctx, type_id, network_id):
        """
        Adds all the attributes defined by a type to a network.

        Args:
            type_id    (int): ID of the type used to get the resource attributes from
            network_id (int): ID of the network 

        Returns:
            List(hydra_complexmodels.ResourceAttr): All the newly created network attributes

        Raises:
            ResourceNotFoundError if the type_id or network_id are not in the DB
        """
        new_resource_attrs = attributes.add_resource_attrs_from_type(
            type_id, 'NETWORK', network_id, **ctx.in_header.__dict__)

        return [ResourceAttr(ra) for ra in new_resource_attrs]

    @rpc(Integer,
         Integer(min_occurs=0, max_occurs=1),
         _returns=SpyneArray(ResourceAttr))
    def get_network_attributes(ctx, network_id, type_id):
        """
        Get all a network's attributes (not the attributes of the nodes and links. just the network itself).

        Args:
            network_id (int): ID of the network 
            type_id    (int) (optional): ID of the type. If specified will only return the resource attributes relative to that type

        Returns:
            List(hydra_complexmodels.ResourceAttr): All the network attributes

        Raises:
            ResourceNotFoundError if the type_id or network_id are not in the DB

 
        """
        resource_attrs = attributes.get_resource_attributes(
            'NETWORK', network_id, type_id)

        return [ResourceAttr(ra) for ra in resource_attrs]

    @rpc(Integer,
         Integer,
         Unicode(pattern="['YN']", default='N'),
         _returns=ResourceAttr)
    def add_node_attribute(ctx, node_id, attr_id, is_var):
        """
        Add a resource attribute to a node.

        Args:
            node_id (int): The ID of the Node
            attr_id (int): THe ID if the attribute being added.
            is_var (char): Y or N. Indicates whether the attribute is a variable or not.

        Returns:
            hydra_complexmodels.ResourceAttr: The newly created node attribute

        Raises:
            ResourceNotFoundError: If the node or attribute do not exist
            HydraError: If this addition causes a duplicate attribute on the node.

        """
        new_ra = attributes.add_resource_attribute('NODE', node_id, attr_id,
                                                   is_var,
                                                   **ctx.in_header.__dict__)

        return ResourceAttr(new_ra)

    @rpc(Integer, Integer, _returns=SpyneArray(ResourceAttr))
    def add_node_attrs_from_type(ctx, type_id, node_id):
        """
        Adds all the attributes defined by a type to a node.

        Args:
            type_id (int): ID of the type used to get the resource attributes from
            node_id (int): ID of the node 

        Returns:
            List(hydra_complexmodels.ResourceAttr): All the newly created node attributes

        Raises:
            ResourceNotFoundError if the type_id or node_id are not in the DB
 
        """
        new_resource_attrs = attributes.add_resource_attrs_from_type(
            type_id, 'NODE', node_id, **ctx.in_header.__dict__)
        return [ResourceAttr(ra) for ra in new_resource_attrs]

    @rpc(Integer,
         Integer(min_occurs=0, max_occurs=1),
         _returns=SpyneArray(ResourceAttr))
    def get_node_attributes(ctx, node_id, type_id):
        """
        Get all a node's attributes.

        Args:
            node_id (int): ID of the node 
            type_id (int) (optional): ID of the type. If specified will only return the resource attributes relative to that type

        Returns:
            List(hydra_complexmodels.ResourceAttr): All the node's attributes

        Raises:
            ResourceNotFoundError if the type_id or node_id do not exist.
        """

        resource_attrs = attributes.get_resource_attributes(
            'NODE', node_id, type_id)

        return [ResourceAttr(ra) for ra in resource_attrs]

    @rpc(Integer,
         Integer(min_occurs=0, max_occurs=1),
         _returns=SpyneArray(ResourceAttr))
    def get_all_node_attributes(ctx, network_id, template_id):
        """
        Get all the resource attributes for all the nodes in the network.

        Args:
            network_id (int): The ID of the network that you want the node attributes from
            template_id (int) (optional): If this is specified, then it will only return the attributes in this template.

        Returns:
            List(hydra_complexmodels.ResourceAttr): The resource attributes of all the nodes in the network.
        """
        resource_attrs = attributes.get_all_resource_attributes(
            'NODE', network_id, template_id)

        return [ResourceAttr(ra) for ra in resource_attrs]

    @rpc(Integer,
         Integer,
         Unicode(pattern="['YN']", default='N'),
         _returns=ResourceAttr)
    def add_link_attribute(ctx, link_id, attr_id, is_var):
        """
        Add a resource attribute to a link.

        Args:
            link_id (int): The ID of the Link
            attr_id (int): THe ID if the attribute being added.
            is_var (char): Y or N. Indicates whether the attribute is a variable or not.

        Returns:
            hydra_complexmodels.ResourceAttr: The newly created link attribute

        Raises:
            ResourceNotFoundError: If the link or attribute do not exist
            HydraError: If this addition causes a duplicate attribute on the link.

        """
        new_ra = attributes.add_resource_attribute('LINK', link_id, attr_id,
                                                   is_var,
                                                   **ctx.in_header.__dict__)

        return ResourceAttr(new_ra)

    @rpc(Integer, Integer, _returns=SpyneArray(ResourceAttr))
    def add_link_attrs_from_type(ctx, type_id, link_id):
        """
        Adds all the attributes defined by a type to a link.

        Args:
            type_id (int): ID of the type used to get the resource attributes from
            link_id (int): ID of the link

        Returns:
            List(hydra_complexmodels.ResourceAttr): All the newly created link attributes

        Raises:
            ResourceNotFoundError if the type_id or link_id are not in the DB
 
        """

        new_resource_attrs = attributes.add_resource_attrs_from_type(
            type_id, 'LINK', link_id, **ctx.in_header.__dict__)
        return [ResourceAttr(ra) for ra in new_resource_attrs]

    @rpc(Integer,
         Integer(min_occurs=0, max_occurs=1),
         _returns=SpyneArray(ResourceAttr))
    def get_link_attributes(ctx, link_id, type_id):
        """
        Get all a link's attributes.

        Args:
            link_id (int): ID of the link 
            type_id (int) (optional): ID of the type. If specified will only return the resource attributes relative to that type

        Returns:
            List(hydra_complexmodels.ResourceAttr): All the link's attributes

        Raises:
            ResourceNotFoundError if the type_id or link_id do not exist.
        """

        resource_attrs = attributes.get_resource_attributes(
            'LINK', link_id, type_id)

        return [ResourceAttr(ra) for ra in resource_attrs]

    @rpc(Integer,
         Integer(min_occurs=0, max_occurs=1),
         _returns=SpyneArray(ResourceAttr))
    def get_all_link_attributes(ctx, network_id, template_id):
        """
        Get all the resource attributes for all the links in the network.

        Args:
            network_id (int): The ID of the network that you want the link attributes from
            template_id (int) (optional): If this is specified, then it will only return the attributes in this template.

        Returns:
            List(hydra_complexmodels.ResourceAttr): The resource attributes of all the links in the network.
        """

        resource_attrs = attributes.get_all_resource_attributes(
            'LINK', network_id, template_id)

        return [ResourceAttr(ra) for ra in resource_attrs]

    @rpc(Integer,
         Integer,
         Unicode(pattern="['YN']", default='N'),
         _returns=ResourceAttr)
    def add_group_attribute(ctx, group_id, attr_id, is_var):
        """
        Add a resource attribute to a group.

        Args:
            group_id (int): The ID of the Group
            attr_id (int): THe ID if the attribute being added.
            is_var (char): Y or N. Indicates whether the attribute is a variable or not.

        Returns:
            hydra_complexmodels.ResourceAttr: The newly created group attribute

        Raises:
            ResourceNotFoundError: If the group or attribute do not exist
            HydraError: If this addition causes a duplicate attribute on the group.

        """

        new_ra = attributes.add_resource_attribute('GROUP', group_id, attr_id,
                                                   is_var,
                                                   **ctx.in_header.__dict__)

        return ResourceAttr(new_ra)

    @rpc(Integer, Integer, _returns=SpyneArray(ResourceAttr))
    def add_group_attrs_from_type(ctx, type_id, group_id):
        """
        Adds all the attributes defined by a type to a group.

        Args:
            type_id (int): ID of the type used to get the resource attributes from
            group_id (int): ID of the group

        Returns:
            List(hydra_complexmodels.ResourceAttr): All the newly created group attributes

        Raises:
            ResourceNotFoundError if the type_id or group_id are not in the DB
 
        """
        new_resource_attrs = attributes.add_resource_attrs_from_type(
            type_id, 'GROUP', group_id, **ctx.in_header.__dict__)
        return [ResourceAttr(ra) for ra in new_resource_attrs]

    @rpc(Integer,
         Integer(min_occurs=0, max_occurs=1),
         _returns=SpyneArray(ResourceAttr))
    def get_group_attributes(ctx, group_id, type_id):
        """
        Get all a group's attributes.

        Args:
            group_id (int): ID of the group 
            type_id (int) (optional): ID of the type. If specified will only return the resource attributes relative to that type

        Returns:
            List(hydra_complexmodels.ResourceAttr): All the group's attributes

        Raises:
            ResourceNotFoundError if the type_id or group_id do not exist.
        """

        resource_attrs = attributes.get_resource_attributes(
            'GROUP', group_id, type_id, **ctx.in_header.__dict__)

        return [ResourceAttr(ra) for ra in resource_attrs]

    @rpc(Integer,
         Integer(min_occurs=0, max_occurs=1),
         _returns=SpyneArray(ResourceAttr))
    def get_all_group_attributes(ctx, network_id, template_id):
        """
        Get all the resource attributes for all the groups in the network.

        Args:
            network_id (int): The ID of the network that you want the group attributes from
            template_id (int) (optional): If this is specified, then it will only return the attributes in this template.

        Returns:
            List(hydra_complexmodels.ResourceAttr): The resource attributes of all the groups in the network.
        """

        resource_attrs = attributes.get_all_resource_attributes(
            'GROUP', network_id, template_id, **ctx.in_header.__dict__)

        return [ResourceAttr(ra) for ra in resource_attrs]

    @rpc(Integer, _returns=Unicode)
    def check_attr_dimension(ctx, attr_id):
        """
        Check that the dimension of the resource attribute data is consistent
        with the definition of the attribute.
        If the attribute says 'volume', make sure every dataset connected
        with this attribute via a resource attribute also has a dimension
        of 'volume'.
        
        Args:
            attr_id (int): The ID of the attribute you want to check

        Returns:
            string: 'OK' if all is well.

        Raises:
            HydraError: If a dimension mismatch is found.
        """

        attributes.check_attr_dimension(attr_id, **ctx.in_header.__dict__)

        return 'OK'

    @rpc(Integer, Integer, _returns=Unicode)
    def set_attribute_mapping(ctx, resource_attr_a, resource_attr_b):
        """
        Define one resource attribute from one network as being the same as
        that from another network.

        Args:
            resource_attr_a (int): The ID of the source resoure attribute
            resource_attr_b (int): The ID of the target resoure attribute

        Returns:
            string: 'OK' if all is well.

        Raises:
            ResourceNotFoundError: If either resource attribute is not found.
        """
        attributes.set_attribute_mapping(resource_attr_a, resource_attr_b,
                                         **ctx.in_header.__dict__)

        return 'OK'

    @rpc(Integer, Integer, _returns=Unicode)
    def delete_attribute_mapping(ctx, resource_attr_a, resource_attr_b):
        """
        Delete a mapping which said one resource attribute from one network 
        was the same as the resource attribute in another.

        Args:
            resource_attr_a (int): The ID of the source resoure attribute
            resource_attr_b (int): The ID of the target resoure attribute

        Returns:
            string: 'OK' if all is well. If the mapping isn't there, it'll still return 'OK', so make sure the IDs are correct! 

        """
        attributes.delete_attribute_mapping(resource_attr_a, resource_attr_b,
                                            **ctx.in_header.__dict__)

        return 'OK'

    @rpc(Integer,
         Integer(min_occurs=0, max_occurs=1),
         _returns=SpyneArray(ResourceAttrMap))
    def get_mappings_in_network(ctx, network_id, network_2_id):
        """
        Get all the resource attribute mappings in a network (both from and to). If another network
        is specified, only return the mappings between the two networks.

        Args:
            network_id (int): The network you want to check the mappings of (both from and to)
            network_2_id (int) (optional): The partner network

        Returns:
            List(hydra_complexmodels.ResourceAttrMap): All the mappings to and from the network(s) in question.
        """
        mapping_rs = attributes.get_mappings_in_network(
            network_id, network_2_id, **ctx.in_header.__dict__)

        mappings = [ResourceAttrMap(m) for m in mapping_rs]
        return mappings

    @rpc(Integer, Integer(min_occurs=0, max_occurs=1), _returns=Unicode)
    def delete_mappings_in_network(ctx, network_id, network_2_id):
        """
        Delete all the resource attribute mappings in a network. If another network
        is specified, only delete the mappings between the two networks.

        Args:
            network_id (int): The network you want to delete the mappings from (both from and to)
            network_2_id (int) (optional): The partner network

        Returns:
            string: 'OK'
        """
        attributes.delete_mappings_in_network(network_id, network_2_id,
                                              **ctx.in_header.__dict__)

        return 'OK'

    @rpc(Integer,
         Integer(min_occurs=0, max_occurs=1),
         _returns=SpyneArray(ResourceAttrMap))
    def get_node_mappings(ctx, node_id, node_2_id):
        """
        Get the mappings for all the attributes of a given node. If a second node
        is specified, return only the mappings between these nodes..

        Args:
            node_id (int): The node you want to delete the mappings from (both from and to)
            node_2_id (int) (optional): The partner node

        Returns:
            List(hydra_complexmodels.ResourceAttrMap): All the mappings to and from the node(s) in question.
        """
        mapping_rs = attributes.get_node_mappings(node_id, node_2_id,
                                                  **ctx.in_header.__dict__)

        mappings = [ResourceAttrMap(m) for m in mapping_rs]
        return mappings

    @rpc(Integer, Integer, _returns=Unicode)
    def check_mapping_exists(ctx, resource_attr_id_source,
                             resource_attr_id_target):
        """
        Check whether a mapping exists between two resource attributes
        This does not check whether a reverse mapping exists, so order is important here.

        Args:
            resource_attr_id_source (int): The source resource attribute 
            resource_attr_id_target (int) (optional): The target resource attribute

        Returns:
            string: 'Y' if a mapping between the source and target exists. 'N' in every other case.

        """
        is_mapped = attributes.check_attribute_mapping_exists(
            resource_attr_id_source, resource_attr_id_target,
            **ctx.in_header.__dict__)

        return is_mapped
Ejemplo n.º 11
0
class City(ComplexModelBase):
    cityName = Unicode(255)
    cityTZDeltaSeconds = Integer(ge=-43200, le=43200)
Ejemplo n.º 12
0
class List(SchemaBase):
    _type_info = [
        ('item_type', XmlAttribute(Unicode(sub_name='itemType'))),
    ]
Ejemplo n.º 13
0
class AnswerServiceResponse(ComplexModel):
    __namespace__ = 'tns'
    dummy_str = Unicode(min_occurs=0, max_occurs=1, nillable=False)
    dummy_num = Integer(min_occurs=1, max_occurs=1, nillable=True)
Ejemplo n.º 14
0
 class SomeService(ServiceBase):
     @srpc(Unicode(pattern=u'x'), _returns=Unicode)
     def some_call(s):
         test(never, reaches, here)
Ejemplo n.º 15
0
 class C(ComplexModel):
     e = Unicode(max_occurs='unbounded')
     a = XmlAttribute(Unicode, attribute_of="e")
Ejemplo n.º 16
0
class OrgExternalType(SmevModel):
    Code = Unicode(type_name="Code", pattern="[A-Z0-9]{4}\d{5}")
    Name = Unicode(type_name="Name")
Ejemplo n.º 17
0
 class cls(ComplexModel):
     __namespace__ = 'tns'
     s = Unicode(max_occurs='unbounded')
Ejemplo n.º 18
0
class ServiceType(SmevModel):
    Mnemonic = Unicode(type_name="Mnemonic", min_occurs=1, max_occurs=1)
    Version = Unicode(type_name="Version",
                      pattern="\d{1,2}\.\d{2}",
                      min_occurs=1,
                      max_occurs=1)
Ejemplo n.º 19
0
 def test_unicode_nullable_mult_cust_false(self):
     assert Unicode(nullable=False).Attributes.nullable == False
     assert Unicode(nullable=False)(5).Attributes.nullable == False
Ejemplo n.º 20
0
class HeaderType(SmevModel):
    NodeId = Unicode(type_name="NodeId")
    MessageId = Unicode(type_name="MessageId")
    TimeStamp = DateTime(type_name="TimeStamp")
    MessageClass = Unicode(type_name="MessageClass",
                           values=["REQUEST", "RESPONSE"])
Ejemplo n.º 21
0
 def test_new_type(self):
     """Customized primitives go into namespace based on module name."""
     custom_type = Unicode(pattern='123')
     self.assertEqual(custom_type.get_namespace(), custom_type.__module__)
Ejemplo n.º 22
0
class AppDocument(SmevModel):
    RequestCode = Unicode(type_name="RequestCode")
    BinaryData = File(type_name="BinaryData", encoding=BINARY_ENCODING_BASE64)
Ejemplo n.º 23
0
 class SomeComplexModel(ComplexModel):
     _type_info = [
         ('a', Unicode),
         ('b', Unicode(default='default')),
     ]
Ejemplo n.º 24
0
class WFMPortalService(DjangoServiceBase):
    """WEB API"""

    __in_header__ = AuthDataHeader
    """
    Создание заявки на аутсорсинг персонала
    """
    @rpc(Unicode(sub_name='guid', min_occurs=1, nillable=False),
         HeadquaterSoapModel.customize(min_occurs=0, nillable=False),
         Date(sub_name='start'),
         Date(sub_name='end'),
         OrganizationSoapModel,
         AgencySoapModel,
         Unicode(sub_name='state', min_occurs=1, nillable=False),
         Array(ShiftSoapModel),
         Unicode(sub_name='comments', min_occurs=0, nillable=False),
         Unicode(sub_name='user_name', min_occurs=0, nillable=False),
         Unicode(sub_name='email', min_occurs=0, nillable=False),
         _returns=Unicode,
         _throws=[AuthenticationError, AuthorizationError, CustomError])
    @soap_logger
    @check_auth_data
    def setOutsourcingRequest(ctx, guid, headquater, start, end, organization,
                              agency, state, shifts, comments, user_name,
                              email):

        auth_and_check_perms(ctx.in_header.login, ctx.in_header.password)

        # TODO remove
        if not headquater:
            db_headquarter = open_headquarter_by_code('mvideo')

        # Магазин, сформировавший запрос
        if headquater:
            db_headquarter = open_headquarter_by_code(headquater.code)
            db_organization = open_organization_by_code(
                organization.code, db_headquarter)
        else:
            db_organization = open_organization_by_code(
                organization.code, None)
            db_headquarter = db_organization.headquater
        if not db_headquarter:
            raise CustomError(
                f'REQUEST {guid}: no headquater with code {headquater.code}')
        if not db_organization:
            raise CustomError(
                f'REQUEST {guid}: no organiztion with code {organization.code}'
            )

        # Агентство, в котором запрашиваем аутсорсинг
        db_agency = open_agency_by_code(agency.code, None)
        if not db_agency:
            raise CustomError(
                f'REQUEST {guid}: no agency with code {agency.code}')

        # Принимаем запросы только в состоянии launched, повторно запросы и запросы без смен не обрабатываем
        if state != 'launched':
            raise CustomError(
                f'REQUEST {guid}: state {state} is differ then launched')
        out_req = OutsourcingRequest.objects.filter(guid=guid).first()
        if out_req or not shifts:
            return {'result': 'ok'}

        # Создаем объект запроса
        if not comments:
            comments = ''
        if not user_name:
            user_name = ''
        if not email:
            email = ''
        out_req = OutsourcingRequest.objects.create(
            guid=guid,
            headquater=db_headquarter,
            organization=db_organization,
            agency=db_agency,
            state='accepted',
            start=start,
            end=end,
            comments=comments,
            user_name=user_name,
            email=email)
        # Создаем связанные с запросом смены
        for s in shifts:
            try:
                job = Job.objects.get(code=s.job.code)
            except Job.DoesNotExist:
                raise CustomError(
                    f'REQUEST {guid}, SHIFT {s.guid}: no job with code {s.job.code}'
                )
            if s.start > s.end:
                raise CustomError(
                    f'REQUEST {guid}, SHIFT {s.guid}: start > end')
            if s.worktime < 0:
                raise CustomError(
                    f'REQUEST {guid}, SHIFT {s.guid}: worktime = {s.worktime} < 0'
                )
            OutsourcingShift.objects.create(guid=s.guid,
                                            headquater=db_headquarter,
                                            state=s.state,
                                            start=s.start,
                                            end=s.end,
                                            worktime=s.worktime,
                                            job=job,
                                            request=out_req,
                                            agency=db_agency,
                                            start_date=s.start)

        # Создаем и отправляем уведомления о новой заявке
        make_notify_data(out_req, 'agency', 'wait_req_template')
        return {'result': 'ok'}

    """
        Получение данных по запросам, чей статус был обновлен раньше определенного времени
    """

    @rpc(DateTime(sub_name='timestamp', min_occurs=1, nillable=False),
         HeadquaterSoapModel.customize(min_occurs=0, nillable=False),
         Integer(sub_name='amount', min_occurs=0, nillable=False),
         _returns=ComplexRequestsResponseSoapModel,
         _throws=[AuthenticationError, AuthorizationError, CustomError])
    @soap_logger
    @check_auth_data
    def getOutsourcingRequests(ctx, dt_change, headquater, amount):
        auth_and_check_perms(ctx.in_header.login, ctx.in_header.password)

        # TODO remove
        if not headquater:
            db_headquarter = open_headquarter_by_code('mvideo')
        else:
            # Клиент
            db_headquarter = open_headquarter_by_code(headquater.code)
        if not db_headquarter:
            raise CustomError(
                f'Headquater {headquater.code} is not registered')

        response = dict()
        response['requests_list'] = []

        # Ограничинваем максимальное количество запросов, возвращаемых за 1 раз
        if not amount or amount < 0:
            amount = 100

        # Поиск смен
        out_requests = OutsourcingRequest.objects.filter(
            headquater=db_headquarter, dt_ready__gt=dt_change, state='ready')
        out_requests = out_requests.order_by('dt_ready')[:amount]

        # Формируем результат
        if not out_requests:
            response['result'] = len(out_requests)
            response['timestamp'] = dt_change
        else:
            response['result'] = len(out_requests)
            response['timestamp'] = out_requests.aggregate(
                timestamp=Max('dt_ready'))['timestamp']
            response['requests_list'] = out_requests

        return response

    """
    Получение данных по запросу и связанным с ним сменам
    """

    @rpc(Unicode(sub_name='guid', min_occurs=1, nillable=False),
         HeadquaterSoapModel.customize(min_occurs=0, nillable=False),
         _returns=ComplexOutsourcingRequestSoapModel,
         _throws=[AuthenticationError, AuthorizationError, CustomError])
    @soap_logger
    @check_auth_data
    def getOutsourcingRequest(ctx, guid, headquater):
        auth_and_check_perms(ctx.in_header.login, ctx.in_header.password)

        # TODO remove
        if not headquater:
            db_headquarter = open_headquarter_by_code('mvideo')
        else:
            # Клиент
            db_headquarter = open_headquarter_by_code(headquater.code)
        if not db_headquarter:
            raise CustomError(
                f'Headquater {headquater.code} is not registered')

        try:
            out_request = OutsourcingRequest.objects.get(
                guid=guid, headquater=db_headquarter)
            shifts = OutsourcingShift.objects.filter(
                request=out_request,
                headquater=db_headquarter).select_related('job')
            out_request.shifts = shifts
            return out_request
        except:
            raise CustomError(
                f'REQUEST {guid}: no OutsourcingRequest is found')

    """
    Получение изменений по сменам на аутсорсинг
    """

    @rpc(DateTime(sub_name='timestamp', min_occurs=1, nillable=False),
         HeadquaterSoapModel.customize(min_occurs=0, nillable=False),
         Integer(sub_name='amount', min_occurs=0, nillable=False),
         _returns=ComplexShiftsResponseSoapModel,
         _throws=[AuthenticationError, AuthorizationError, CustomError])
    @soap_logger
    @check_auth_data
    def getOutsourcingShifts(ctx, dt_change, headquater, amount):
        auth_and_check_perms(ctx.in_header.login, ctx.in_header.password)

        # TODO remove
        if not headquater:
            db_headquarter = open_headquarter_by_code('mvideo')
        else:
            # Клиент
            db_headquarter = open_headquarter_by_code(headquater.code)
        if not db_headquarter:
            raise CustomError(
                f'Headquater {headquater.code} is not registered')

        response = dict()
        response['shifts_list'] = []

        # Ограничинваем максимальное количество смен, возвращаемых за 1 раз
        if not amount or amount < 0:
            amount = 100

        # Поиск смен
        out_shifts = OutsourcingShift.objects.filter(headquater=db_headquarter,
                                                     dt_change__gt=dt_change,
                                                     state='accept')
        out_shifts = out_shifts.order_by('dt_change').select_related(
            'agency_employee')[:amount]

        # Получение ТН сотрудника в организации на основе OrgHistory
        for shift in out_shifts:
            if shift.agency_employee:
                shift.agency_employee.oh_number = shift.get_employee_number_in_organization(
                )
        # Формируем результат
        if not out_shifts:
            response['result'] = len(out_shifts)
            response['timestamp'] = dt_change
        else:
            response['result'] = len(out_shifts)
            response['timestamp'] = out_shifts.aggregate(
                timestamp=Max('dt_change'))['timestamp']
            response['shifts_list'] = out_shifts

        return response

    """
    Получение смен промоутеров
    """

    @rpc(DateTime(sub_name='timestamp', min_occurs=1, nillable=False),
         HeadquaterSoapModel.customize(min_occurs=0, nillable=False),
         AgencySoapModel.customize(min_occurs=0, nillable=False),
         Integer(sub_name='amount', min_occurs=0, nillable=False),
         _returns=ComplexPromoShiftsResponseSoapModel,
         _throws=[AuthenticationError, AuthorizationError, CustomError])
    @soap_logger
    @check_auth_data
    def getPromoShifts(ctx, dt_change, headquater, agency, amount):
        return _calc_shifts(ctx,
                            dt_change,
                            headquater,
                            agency,
                            amount,
                            party='promo')

    """
    Получение смен брокеров
    """

    @rpc(DateTime(sub_name='timestamp', min_occurs=1, nillable=False),
         HeadquaterSoapModel.customize(min_occurs=0, nillable=False),
         AgencySoapModel.customize(min_occurs=0, nillable=False),
         Integer(sub_name='amount', min_occurs=0, nillable=False),
         _returns=ComplexPromoShiftsResponseSoapModel,
         _throws=[AuthenticationError, AuthorizationError, CustomError])
    @soap_logger
    @check_auth_data
    def getBrokerShifts(ctx, dt_change, headquater, agency, amount):
        return _calc_shifts(ctx,
                            dt_change,
                            headquater,
                            agency,
                            amount,
                            party='broker')

    """
    Удаление смены из заявки на аутсорсинг по решению управляюего магазином
    """

    @rpc(Array(ShiftDeleteSoapModel),
         HeadquaterSoapModel.customize(min_occurs=0, nillable=False),
         _returns=Unicode,
         _throws=[AuthenticationError, AuthorizationError, CustomError])
    @soap_logger
    @check_auth_data
    def deleteOutsourcingShifts(ctx, shifts, headquater):
        auth_and_check_perms(ctx.in_header.login, ctx.in_header.password)

        # TODO remove
        if not headquater:
            db_headquarter = open_headquarter_by_code('mvideo')
        else:
            # Клиент
            db_headquarter = open_headquarter_by_code(headquater.code)
        if not db_headquarter:
            raise CustomError(
                f'Headquater {headquater.code} is not registered')

        # Выходим, если массив смен не задан
        if not shifts:
            return {'result': 'ok'}

        # Помечаем смены как удаленные и формируем уведомления
        for shift in shifts:
            # ----------------------------------------------------------
            out_shift = OutsourcingShift.objects.filter(
                guid=shift.guid, headquater=db_headquarter).first()
            if not out_shift:
                continue
            # Создаем и отправляем уведомления об удаленной смене
            make_notify_data(out_shift, 'agency', 'delete_shift_template')

            # Меняем состояние на удалена
            out_shift.state = 'delete'
            out_shift.save(update_fields=['state'])
            # -----------------------------------------------------------
        return {'result': 'ok'}

    """
    Получение изменений в данных сотрудников
    """

    @rpc(DateTime(sub_name='timestamp', min_occurs=1, nillable=False),
         HeadquaterSoapModel.customize(min_occurs=0, nillable=False),
         Integer(sub_name='amount', min_occurs=1, nillable=False),
         _returns=ComplexEmployeeEventResponseSoapModel,
         _throws=[AuthenticationError, AuthorizationError, CustomError])
    @soap_logger
    @check_auth_data
    def getEmployeeEvents(ctx, timestamp, headquater, amount):
        auth_and_check_perms(ctx.in_header.login, ctx.in_header.password)

        # Ограничинваем максимальное количество событий, возвращаемых за 1 раз
        if amount <= 0:
            amount = 100

        # TODO remove
        if not headquater:
            db_headquarter = open_headquarter_by_code('mvideo')
        else:
            # Клиент
            db_headquarter = open_headquarter_by_code(headquater.code)
        if not db_headquarter:
            raise CustomError(
                f'Headquater {headquater.code} is not registered')

        # Поиск событий, начиная с заданного в запросе timestamp
        response = dict()
        response['events_list'] = []
        events = EmployeeEvent.objects.filter(dt_created__gt=timestamp, headquater=db_headquarter). \
                     select_related('agency_employee', 'agency').order_by('id')[:amount]
        # Обогощаем найденные события доп. полями
        for event in events:
            # Тип агентства
            event.agency.party = event.agency.headquater.party
            # Документы сотрудника
            event.agency_employee.documents = EmployeeDoc.objects.filter(
                agency_employee=event.agency_employee).order_by('-id')
            # Обнуляем лишние поля
            if event.kind != 'recruitment':
                event.recruitment_date = None
            if event.kind != 'dismissal':
                event.dismissal_reason = None
                event.dismissal_date = None
                event.blacklist = None
        # Добавляем возвращемые события в ответное сообщение
        response['result'] = len(events)
        if events:
            response['timestamp'] = events.aggregate(
                timestamp=Max('dt_created'))['timestamp']
            response['events_list'] = events
        return response

    """DEPRICATED"""

    @rpc(HeadquaterSoapModel.customize(min_occurs=1, nillable=False),
         OrganizationSoapModel.customize(min_occurs=1, nillable=False),
         AgencySoapModel.customize(min_occurs=1, nillable=False),
         EmployeeMinSoapModel,
         EventSoapModel.customize(sub_name='event'),
         Unicode(sub_name='kind', min_occurs=1, nillable=False),
         Unicode(sub_name='number', min_occurs=0, nillable=False),
         Date(sub_name='recruitment_date', min_occurs=0, nillable=False),
         Date(sub_name='recruitment_state', min_occurs=0, nillable=False),
         Date(sub_name='dismissal_date', min_occurs=0, nillable=False),
         Unicode(sub_name='reject_reason', min_occurs=0, nillable=False),
         Unicode(sub_name='dismissal_reason', min_occurs=0, nillable=False),
         _returns=Unicode,
         _throws=[AuthenticationError, AuthorizationError, CustomError])
    @soap_logger
    @check_auth_data
    def setEventHistory(ctx, headquater, organization, agency, employee,
                        employeeevent, kind, number, recruitment_date,
                        recruitment_state, dismissal_date, reject_reason,
                        dismissal_reason):
        raise CustomError('Method is deprocated')

        # TODO изменить проверку доступа с is_superuser

        auth_and_check_perms(ctx.in_header.login, ctx.in_header.password)

        headquater_id = get_headquater_id(headquater.code)

        org = Organization.objects.get(code=organization.code,
                                       headquater_id=headquater_id)
        if not org:
            raise CustomError('No organiztion')

        agn = Agency.objects.get(code=agency.code)
        if not agn:
            raise CustomError('No agency')

        emp = AgencyEmployee.objects.get(number=employee.number, agency=agn)
        if not emp:
            raise CustomError('No employee')

        event = EmployeeEvent.objects.get(guid=employeeevent.guid)

        user = User.objects.get(username=ctx.in_header.login)

        if kind not in dict(EVENT_HISTORY_KIND_CHOICES):
            raise CustomError('No kind')
        elif kind == 'accept_recruitment':

            if not recruitment_date:
                raise CustomError('No recruitment_date')

            if recruitment_state not in ['active', 'inactive']:
                raise CustomError('No recruitment_state')
            """Создаем объект внешнего события"""
            EmployeeHistory.objects.create(user=user,
                                           headquater_id=headquater_id,
                                           organization=org,
                                           event=event,
                                           agency_employee=emp,
                                           agency=agn,
                                           kind=kind,
                                           recruitment_date=recruitment_date,
                                           recruitment_state=recruitment_state)

            if recruitment_state == 'active':
                """Создаем объект назначения"""
                OrgHistory.objects.create(headquater_id=headquater_id,
                                          organization=org,
                                          agency_employee=emp,
                                          number=number,
                                          start=recruitment_date)
            """Устанавливаем EmployeeEvent флаг, что ответ на него получен"""
            event.answer_received = True
            event.save(update_fields=['answer_received'])
        elif kind == 'reject_recruitment':

            if not reject_reason:
                raise CustomError('No reject_reason')
            """Создаем объект внешнего события"""
            EmployeeHistory.objects.create(user=user,
                                           headquater_id=headquater_id,
                                           organization=org,
                                           event=event,
                                           agency_employee=emp,
                                           agency=agn,
                                           kind=kind,
                                           reject_reason=reject_reason)
            """Устанавливаем EmployeeEvent флаг, что ответ на него получен"""
            event.answer_received = True
            event.save(update_fields=['answer_received'])

        elif kind == 'dismissal':

            if not dismissal_date or not dismissal_reason:
                raise CustomError('No dismissal date or reason')
            """Ищем назначение и устанавливаем дату увольнения"""
            org_history = OrgHistory.objects.get(organization=org,
                                                 agency_employee=emp)
            if not org_history:
                raise CustomError('No OrgHistory')
            org_history.end = dismissal_date - timedelta(days=1)
            org_history.save(update_fields=['end'])
            """Ищем смены данного сотрудника после даты увольнения и снимаем назначение"""
            OutsourcingShift.objects.filter(
                agency_employee=emp,
                start_date__gt=dismissal_date - timedelta(days=1),
                headquater_id=headquater_id).update(agency_employee=None)
            """Создаем объект внешнего события"""
            EmployeeHistory.objects.create(user=user,
                                           headquater_id=headquater_id,
                                           organization=org,
                                           event=event,
                                           agency_employee=emp,
                                           agency=agn,
                                           kind=kind,
                                           dismissal_date=dismissal_date,
                                           dismissal_reason=dismissal_reason)
            """Устанавливаем EmployeeEvent флаг, что ответ на него получен"""
            event.answer_received = True
            event.save(update_fields=['answer_received'])
            """Устанавливаем сотруднику дату обновления данных по API"""
            event.agency_employee.last_external_update = timezone.now()
            event.agency_employee.save(update_fields=['last_external_update'])

        return "ok"

    """Подтверждение или отказ в приеме сотрудника из кадровой системы клиента"""

    @rpc(EventSoapModel2.customize(sub_name='event',
                                   min_occurs=1,
                                   nillable=False),
         Unicode(sub_name='status', min_occurs=1, nillable=False),
         Unicode(sub_name='recruitmentState',
                 min_occurs=0,
                 nillable=False,
                 default='active'),
         Date(sub_name='recruitmentDate', min_occurs=0, nillable=False),
         Unicode(sub_name='externalNumber', min_occurs=0, nillable=False),
         Unicode(sub_name='rejectReason', min_occurs=0, nillable=False),
         _returns=Unicode,
         _throws=[AuthenticationError, AuthorizationError, CustomError])
    @soap_logger
    @check_auth_data
    def setRecruitmentStatus(ctx, employeeevent, status, recruitmentState,
                             recruitmentDate, externalNumber, rejectReason):
        user = User.objects.get(username=ctx.in_header.login)
        auth_and_check_perms(ctx.in_header.login, ctx.in_header.password)

        # Проверка параметров
        event = EmployeeEvent.objects.get(guid=employeeevent.guid)
        if not event:
            raise CustomError(f'Event {employeeevent.guid} is undefined')
        if recruitmentState and recruitmentState not in ['active', 'inactive']:
            raise CustomError('No recruitmentState')
        if status not in ['accept', 'reject']:
            return

        # Подтверждение регистрации
        if status == 'accept':
            error = accept_employee_attach(user, event, recruitmentState,
                                           recruitmentDate, externalNumber)
        # Регистрация отклонена
        else:
            error = reject_employee_attach(user, event, rejectReason)
        # Обработчик ошибок
        if error:
            raise CustomError(error)

        # Устанавливаем сотруднику дату обновления данных по API
        event.agency_employee.last_external_update = timezone.now()
        event.agency_employee.save(update_fields=['last_external_update'])

        return

    """Открепление сотрудника от клиента по запросу из кадровой системы"""

    @rpc(HeadquaterSoapModel.customize(min_occurs=1, nillable=False),
         OrganizationSoapModel,
         AgencySoapModel.customize(min_occurs=1, nillable=False),
         Unicode(sub_name='externalNumber', min_occurs=1, nillable=False),
         Date(sub_name='dismissalDate', min_occurs=1, nillable=False),
         Unicode(sub_name='dismissalReason', min_occurs=1, nillable=False),
         Boolean(sub_name='blacklist', min_occurs=1, nillable=False),
         _returns=Unicode,
         _throws=[AuthenticationError, AuthorizationError, CustomError])
    @soap_logger
    @check_auth_data
    def dismissEmployee(ctx, headquater, organization, agency, ext_number,
                        dismissal_date, dismissal_reason, blacklist):
        user = User.objects.get(username=ctx.in_header.login)
        auth_and_check_perms(ctx.in_header.login, ctx.in_header.password)

        # Проверка параметров
        db_headquarter = open_headquarter_by_code(headquater.code)
        if not db_headquarter:
            raise CustomError(f'Headquater {headquater.code} is not found')
        if organization:
            db_organization = open_organization_by_code(
                organization.code, db_headquarter)
            if not db_organization:
                raise CustomError(
                    f'Organization {organization.code} is not found')
        else:
            db_organization = None
        db_agency = open_agency_by_code(agency.code, None)
        if not db_agency:
            raise CustomError(f'Agency {agency.code} is not found')

        # Определяем увольняемого сотрудника
        employees = employees_by_ext_number(db_headquarter, db_agency,
                                            ext_number)
        for employee in employees:
            dismiss_employee(user, employee, dismissal_date, dismissal_reason,
                             blacklist, db_headquarter, db_organization)
            # Устанавливаем сотруднику дату обновления данных по API
            employee.last_external_update = timezone.now()
            employee.save(update_fields=['last_external_update'])
        return

    ########
    @rpc(HeadquaterSoapModel.customize(min_occurs=1, nillable=False),
         Array(OrgunitSoapModel.customize(min_occurs=1, nillable=False)),
         Array(OrglinkSoapModel.customize(min_occurs=0, nillable=False)),
         _returns=Unicode,
         _throws=[AuthenticationError, AuthorizationError, CustomError])
    @soap_logger
    @check_auth_data
    def setOrgunits(ctx, headquater, orgunits, orglinks):
        """Set Orgunits. Синхронизитрует орг. структуру на основе данных из портала планирования"""

        auth_and_check_perms(ctx.in_header.login, ctx.in_header.password)

        # Headquarter
        headquater_id = get_headquater_id(headquater.code)

        # Organizations
        orgunits_received = 0
        orgunits_created = 0
        orgunits_errors = 0
        if orgunits:
            for orgunit in orgunits:
                orgunits_received += 1
                org, org_created = Organization.objects.get_or_create(
                    code=orgunit.code, headquater_id=headquater_id)
                if org_created:
                    orgunits_created += 1
                org.name = orgunit.name
                org.address = orgunit.address
                org.kind = 'store'
                if orgunit.parent and org_created:
                    parent_org = Organization.objects.filter(
                        code=orgunit.parent.code,
                        headquater_id=headquater_id).first()
                    if parent_org:
                        org.parent = parent_org
                    else:
                        default, default_created = Organization.objects.get_or_create(
                            code=headquater.code + '_city_undefined',
                            name='Город не определен',
                            headquater_id=headquater_id,
                            kind='city')
                        org.parent = default
                org.last_external_update = timezone.now()
                org.save()

        # OrgLinks
        orglinks_received = 0
        orglinks_created = 0
        orglinks_errors = 0
        if orglinks:
            for orglink_imp in orglinks:
                orglinks_received += 1
                organization = Organization.objects.filter(
                    code=orglink_imp.organization.code).first()
                if not organization:
                    orglinks_errors += 1
                    continue
                agency = Agency.objects.filter(
                    code=orglink_imp.agency.code).first()
                if not agency:
                    orglinks_errors += 1
                    continue
                _, orglink_created = OrgLink.objects.get_or_create(
                    agency=agency,
                    organization=organization,
                    headquater_id=headquater_id)
                if orglink_created:
                    orglinks_created += 1

        return {
            'result': 'ok',
            'orgunits_received': orgunits_received,
            'orgunits_created': orgunits_created,
            'orgunits_errors': orgunits_errors,
            'orglinks_received': orglinks_received,
            'orglinks_created': orglinks_created,
            'orglinks_errors': orglinks_errors,
        }

    @rpc(HeadquarterSoapModel.customize(min_occurs=1, nillable=False),
         UserExtSoapModel.customize(sub_name='user',
                                    min_occurs=1,
                                    nillable=False),
         Array(AccessProfileSoapModel,
               sub_name='accessProfiles').customize(min_occurs=1,
                                                    nillable=False),
         _throws=[
             AuthenticationError, AuthorizationError,
             error.ResourceNotFoundError
         ])
    @soap_logger
    @check_auth_data
    def setUser(ctx, headquarter, user, access_list):
        auth_and_check_perms(ctx.in_header.login, ctx.in_header.password)

        # Обновляем или создаем сотрудника
        user_defaults = {
            'first_name': user.first_name,
            'last_name': user.last_name,
            'email': user.email,
            'is_active': user.is_active
        }
        db_user, created = User.objects.update_or_create(
            username=user.username, defaults=user_defaults)
        db_headquarter = open_headquarter_by_code(headquarter.code)
        db_access_role = None

        # Установка прав доступа
        if access_list is None:
            access_list = []

        for access_profile in access_list:
            try:
                db_organization = open_organization_by_code(
                    access_profile.unit.code, db_headquarter)
            except error.ResourceNotFoundError:
                continue

            if access_profile.role is not None:
                db_access_role = open_role_by_code(access_profile.role.code)

            if db_access_role is None:
                raise error.ResourceNotFoundError('accessRole')

            profile, _ = AccessProfile.objects.update_or_create(
                user=db_user,
                unit_type=ContentType.objects.get_for_model(db_organization),
                unit_id=db_organization.id,
                role=db_access_role,
                headquater=db_headquarter)
Ejemplo n.º 25
0
class CrimeService(ServiceBase):
    @srpc(Float, Float, Float, _returns=Unicode(String))
    def checkcrime(lat,lon, radius):
        url = "https://api.spotcrime.com/crimes.json?lat={}&lon={}&radius={}&key=.".format(lat,lon,radius)
        data = requests.get(url).json()
        
        totalCrime=0
        
        EventTimeCountDict = {'c1': 0, 'c2': 0, 'c3': 0, 'c4': 0, 'c5': 0, 'c6': 0, 'c7': 0, 'c8': 0}
        CrimeListDict = {}
        StreetListDict = {}
        totalCrime=len(data["crimes"])
        
        for i in range(len(data["crimes"])):
            crime_type= data["crimes"][i]["type"]
            crime_datetime= data["crimes"][i]["date"]
            crime_time = CrimeService.find_time(crime_datetime)
            CrimeService.CountForEventTime(crime_time,i, EventTimeCountDict=EventTimeCountDict)
            crime_address= data["crimes"][i]["address"]
            CrimeService.findStreet(crime_address, StreetListDict)
            
            if not crime_type in CrimeListDict:
                CrimeListDict[crime_type]=1
            else:
                CrimeListDict[crime_type]+=1
        
        SortedStreetDict = dict(sorted(StreetListDict.items(), reverse=True, key= operator.itemgetter(1))[:3])
                
        DangerousStreetDict = []    
                
        for key in SortedStreetDict:
            DangerousStreetDict.append(key)
        
        
        c1 = EventTimeCountDict['c1'];
        c2 = EventTimeCountDict['c2'];
        c3 = EventTimeCountDict['c3'];
        c4 = EventTimeCountDict['c4'];
        c5 = EventTimeCountDict['c5'];
        c6 = EventTimeCountDict['c6'];
        c7 = EventTimeCountDict['c7'];
        c8 = EventTimeCountDict['c8'];
        
        
                
        TimeCounterDict = {'12:01am-3am': c1, '3:01am-6am': c2, '6:01am-9am': c3, '9:01am-12noon': c4, '12:01pm-3pm': c5, '3:01pm-6pm': c6, '6:01pm-9pm': c7, '9:01pm-12midnight': c8}
    
        data_print={"total_crime" : totalCrime, "the_most_dangerous_streets" : DangerousStreetDict, "crime_type_count" : CrimeListDict, "event_type_count": TimeCounterDict}
        return data_print
        
    @staticmethod
    def  find_time(crimedt):
        date = datetime.datetime.strptime(crimedt, "%m/%d/%y %I:%M %p")
        dt1 = date.time()
        return date
        
    @staticmethod
    def CountForEventTime(crime_time,crime, EventTimeCountDict):
        year = crime_time.year
        month = crime_time.month
        day = crime_time.day

        dt1 = datetime.datetime(year, month, day, 00, 01, 00)
        dt2 = datetime.datetime(year, month, day, 03, 00, 00)

        if dt1 <= crime_time <= dt2:
            EventTimeCountDict['c1'] = EventTimeCountDict['c1'] + 1
            return EventTimeCountDict

        dt1 = datetime.datetime(year, month, day, 03, 01, 00)
        dt2 = datetime.datetime(year, month, day, 06, 00, 00)

        if dt1 <= crime_time <= dt2:
            EventTimeCountDict['c2'] = EventTimeCountDict['c2'] + 1
            return EventTimeCountDict

        dt1 = datetime.datetime(year, month, day, 06, 01, 00)
        dt2 = datetime.datetime(year, month, day, 9, 1, 00)

        if dt1 <= crime_time <= dt2:
            EventTimeCountDict['c3'] = EventTimeCountDict['c3'] + 1
            return EventTimeCountDict

        dt1 = datetime.datetime(year, month, day, 9, 01, 00)
        dt2 = datetime.datetime(year, month, day, 12, 1, 00)

        if dt1 <= crime_time <= dt2:
            EventTimeCountDict['c4'] = EventTimeCountDict['c4'] + 1
            return EventTimeCountDict

        dt1 = datetime.datetime(year, month, day, 12, 01, 00)
        dt2 = datetime.datetime(year, month, day, 15, 00, 00)

        if dt1 <= crime_time <= dt2:
            EventTimeCountDict['c5'] = EventTimeCountDict['c5'] + 1
            return EventTimeCountDict

        dt1 = datetime.datetime(year, month, day, 15, 01, 00)
        dt2 = datetime.datetime(year, month, day, 18, 00, 00)

        if dt1 <= crime_time <= dt2:
            EventTimeCountDict['c6'] = EventTimeCountDict['c6'] + 1
            return EventTimeCountDict

        dt1 = datetime.datetime(year, month, day, 18, 01, 00)
        dt2 = datetime.datetime(year, month, day, 21, 00, 00)

        if dt1 <= crime_time <= dt2:
            EventTimeCountDict['c7'] = EventTimeCountDict['c7'] + 1
            return EventTimeCountDict
    
        EventTimeCountDict['c8'] = EventTimeCountDict['c8'] + 1
        return EventTimeCountDict
    
    @staticmethod
    def findStreet(address, StreetListDict):
        
        matching1 = re.search(r'[\d\w\s]+OF ([\w\s\d]+ BL)', address)
        if matching1:
            street = matching1.group(1)
            if not street in StreetListDict:
                StreetListDict[street] = 1
            else:
                StreetListDict[street] = StreetListDict[street] + 1
            return StreetListDict

        matching2 = re.search(r'([\d\w\s]+ST) & ([\w\s\d]+ST)', address)
        if matching2:
            street1 = matching2.group(1)
            street2 = matching2.group(2)
            if not street1 in StreetListDict:
                StreetListDict[street1] = 1
            else:
                StreetListDict[street1] = StreetListDict[street1] + 1

            if not street2 in StreetListDict:
                StreetListDict[street2] = 1
            else:
                StreetListDict[street2] = StreetListDict[street2] + 1
            return StreetListDict
            
        matching3 = re.search(r'[\d\w\s]+OF ([\w\s\d]+ ST)', address)
        if matching3:
            street = matching3.group(1)
            
            if not street in StreetListDict:
                StreetListDict[street] = 1
            else:
                StreetListDict[street] = StreetListDict[street] + 1
            return StreetListDict

        

        matching4 = re.search(r'[\d\w\s]+OF ([\w\s\d]+ AV)', address)
        if matching4:
            street = matching4.group(1)
            if not street in StreetListDict:
                StreetListDict[street] = 1
            else:
                StreetListDict[street] = StreetListDict[street] + 1
            return StreetListDict
        
        matching5 = re.search(r'[\d\w\s]+OF ([\w\s\d]+ DR)', address)
        if matching5:
            street = matching5.group(1)
            if not street in StreetListDict:
                StreetListDict[street] = 1
            else:
                StreetListDict[street] = StreetListDict[street] + 1
            return StreetListDict
Ejemplo n.º 26
0
 class SomeOtherClass(NewTableModel):
     __tablename__ = 'some_class'
     __table_args__ = {"sqlite_autoincrement": True}
     id = Integer32(primary_key=True)
     s = Unicode(64)
Ejemplo n.º 27
0
 class SomeService(ServiceBase):
     @srpc(Unicode(max_occurs=Decimal('inf')),
           _returns=Unicode(max_occurs=Decimal('inf')))
     def some_call(s):
         return s
Ejemplo n.º 28
0
 class SomeOtherClass(ComplexModel):
     id = Integer32
     s = Unicode(64)
Ejemplo n.º 29
0
class Include(SchemaBase):
    schema_location = XmlAttribute(Unicode(sub_name="schemaLocation"))
Ejemplo n.º 30
0
class TemplateService(HydraService):
    """
        The template SOAP service
    """
    @rpc(Unicode, _returns=Template)
    def upload_template_xml(ctx, template_xml):
        """
            Add the template, type and typeattrs described
            in an XML file.

            Delete type, typeattr entries in the DB that are not in the XML file
            The assumption is that they have been deleted and are no longer required.
        """
        tmpl_i = template.upload_template_xml(template_xml,
                                              **ctx.in_header.__dict__)

        return Template(tmpl_i)

    @rpc(Unicode, Integer, _returns=SpyneArray(TypeSummary))
    def get_matching_resource_types(ctx, resource_type, resource_id):
        """
            Get the possible types of a resource by checking its attributes
            against all available types.

            @returns A list of TypeSummary objects.
        """
        types = template.get_matching_resource_types(resource_type,
                                                     resource_id,
                                                     **ctx.in_header.__dict__)
        ret_types = [TypeSummary(ts) for ts in types]
        return ret_types

    @rpc(SpyneArray(ResourceTypeDef), _returns=SpyneArray(TemplateType))
    def assign_types_to_resources(ctx, resource_types):
        """Assign new types to list of resources.
        This function checks if the necessary
        attributes are present and adds them if needed. Non existing attributes
        are also added when the type is already assigned. This means that this
        function can also be used to update resources, when a resource type has
        changed.
        """
        types = template.assign_types_to_resources(resource_types,
                                                   **ctx.in_header.__dict__)
        ret_val = [TemplateType(t) for t in types]
        return ret_val

    @rpc(Integer, Unicode, Integer, _returns=TypeSummary)
    def assign_type_to_resource(ctx, type_id, resource_type, resource_id):
        """Assign new type to a resource. This function checks if the necessary
        attributes are present and adds them if needed. Non existing attributes
        are also added when the type is already assigned. This means that this
        function can also be used to update resources, when a resource type has
        changed.
        """
        templatetype = template.assign_type_to_resource(
            type_id, resource_type, resource_id, **ctx.in_header.__dict__)
        ret_type = TypeSummary()
        ret_type.name = templatetype.type_name
        ret_type.id = templatetype.type_id
        ret_type.template_name = templatetype.template.template_name
        ret_type.template_id = templatetype.template.template_id

        return ret_type

    @rpc(Integer, Integer, _returns=Unicode)
    def apply_template_to_network(ctx, template_id, network_id):
        """
            Given a template and a network, try to match up and assign
            all the nodes & links in the network to the types in the template
        """
        template.apply_template_to_network(template_id, network_id,
                                           **ctx.in_header.__dict__)
        return 'OK'

    @rpc(Integer, Integer, _returns=Unicode)
    def set_network_template(ctx, template_id, network_id):
        """
            Given a template and a network, try to match up and assign
            all the nodes & links in the network to the types in the template
        """
        template.set_network_template(template_id, network_id,
                                      **ctx.in_header.__dict__)
        return 'OK'

    @rpc(Integer,
         Integer,
         Unicode(pattern="[YN]", default='N'),
         _returns=Unicode)
    def remove_template_from_network(ctx, network_id, template_id,
                                     remove_attrs):
        """
            Given a template and a network, try to match up and assign
            all the nodes & links in the network to the types in the template
        """
        template.remove_template_from_network(network_id, template_id,
                                              remove_attrs,
                                              **ctx.in_header.__dict__)
        return 'OK'

    @rpc(Integer, Unicode, Integer, _returns=Unicode)
    def remove_type_from_resource(ctx, type_id, resource_type, resource_id):
        """

            Remove a resource type trom a resource
        """
        template.remove_type_from_resource(type_id, resource_type, resource_id,
                                           **ctx.in_header.__dict__)

        return 'OK'

    @rpc(Template, _returns=Template)
    def add_template(ctx, tmpl):
        """
            Add template and a type and typeattrs.
        """
        tmpl_i = template.add_template(tmpl, **ctx.in_header.__dict__)

        return Template(tmpl_i)

    @rpc(Template, _returns=Template)
    def update_template(ctx, tmpl):
        """
            Update template and a type and typeattrs.
        """
        tmpl_i = template.update_template(tmpl, **ctx.in_header.__dict__)
        return Template(tmpl_i)

    @rpc(Integer, _returns=Template)
    def delete_template(ctx, template_id):
        """
            Update template and a type and typeattrs.
        """
        template.delete_template(template_id, **ctx.in_header.__dict__)
        return 'OK'

    @rpc(_returns=SpyneArray(Template))
    def get_templates(ctx):
        """
            Get all resource template templates.
        """
        tmpls = template.get_templates(**ctx.in_header.__dict__)
        ret_templates = [Template(t) for t in tmpls]

        return ret_templates

    @rpc(Integer, Integer, _returns=Unicode)
    def remove_attr_from_type(ctx, type_id, attr_id):
        """

            Remove an attribute from a type
        """
        success = 'OK'
        template.remove_attr_from_type(type_id, attr_id,
                                       **ctx.in_header.__dict__)
        return success

    @rpc(Integer, _returns=Template)
    def get_template(ctx, template_id):
        """
            Get a specific resource template template, either by ID or name.
        """
        tmpl_i = template.get_template(template_id, **ctx.in_header.__dict__)
        tmpl = Template(tmpl_i)

        return tmpl

    @rpc(Unicode, _returns=Template)
    def get_template_by_name(ctx, template_name):
        """
            Get a specific resource template, either by ID or name.
        """
        tmpl_i = template.get_template_by_name(template_name,
                                               **ctx.in_header.__dict__)
        if tmpl_i is not None:
            tmpl = Template(tmpl_i)

            return tmpl
        else:
            return None

    @rpc(TemplateType, _returns=TemplateType)
    def add_templatetype(ctx, templatetype):
        """
            Add a template type with typeattrs.
        """

        tmpl_type = template.add_templatetype(templatetype,
                                              **ctx.in_header.__dict__)

        return TemplateType(tmpl_type)

    @rpc(TemplateType, _returns=TemplateType)
    def update_templatetype(ctx, templatetype):
        """
            Update a resource type and its typeattrs.
            New typeattrs will be added. typeattrs not sent will be ignored.
            To delete typeattrs, call delete_typeattr
        """
        type_i = template.update_templatetype(templatetype,
                                              **ctx.in_header.__dict__)
        return TemplateType(type_i)

    @rpc(Integer, _returns=Template)
    def delete_templatetype(ctx, type_id):
        """
            Update template and a type and typeattrs.
        """
        template.delete_templatetype(type_id, **ctx.in_header.__dict__)
        return 'OK'

    @rpc(Integer, _returns=TemplateType)
    def get_templatetype(ctx, type_id):
        """
            Get a specific resource type by ID.
        """
        type_i = template.get_templatetype(type_id, **ctx.in_header.__dict__)
        templatetype = TemplateType(type_i)
        return templatetype

    @rpc(Integer, Unicode, _returns=TemplateType)
    def get_templatetype_by_name(ctx, template_id, type_name):
        """
            Get a specific resource type by name.
        """

        type_i = template.get_templatetype_by_name(template_id, type_name,
                                                   **ctx.in_header.__dict__)
        tmpltype = TemplateType(type_i)

        return tmpltype

    @rpc(TypeAttr, _returns=TemplateType)
    def add_typeattr(ctx, typeattr):
        """
            Add an typeattr to an existing type.
        """
        updated_template_type = template.add_typeattr(typeattr,
                                                      **ctx.in_header.__dict__)

        ta = TemplateType(updated_template_type)
        return ta

    @rpc(TypeAttr, _returns=Unicode)
    def delete_typeattr(ctx, typeattr):
        """
            Remove an typeattr from an existing type
        """
        success = 'OK'
        template.delete_typeattr(typeattr, **ctx.in_header.__dict__)
        return success

    @rpc(Integer, _returns=Unicode)
    def get_network_as_xml_template(ctx, network_id):
        """
            Turn an existing network into an xml template
            using its attributes.
            If an optional scenario ID is passed in, default
            values will be populated from that scenario.
        """
        template_xml = template.get_network_as_xml_template(
            network_id, **ctx.in_header.__dict__)

        return template_xml

    @rpc(Integer, Integer, Integer, _returns=ValidationError)
    def validate_attr(ctx, resource_attr_id, scenario_id, template_id):
        """
            Validate that the value of a specified resource attribute is valid
            relative to the data restrictions specified on the template. If no
            template is specified, (set as null), then validation will be made
            against every template on the network.
        """
        error_dict = template.validate_attr(resource_attr_id, scenario_id,
                                            template_id)
        if error_dict is None:
            return None

        error = ValidationError(
            ref_key=error_dict.get('ref_key'),
            ref_id=error_dict.get('ref_id'),
            ref_name=error_dict.get('ref_name'),
            resource_attr_id=error_dict.get('resource_attr_id'),
            attr_id=error_dict.get('attr_id'),
            attr_name=error_dict.get('attr_name'),
            dataset_id=error_dict.get('dataset_id'),
            scenario_id=error_dict.get('scenario_id'),
            template_id=error_dict.get('template_id'),
            error_text=error_dict.get('error_text'))
        return error

    @rpc(SpyneArray(Integer32),
         Integer,
         Integer,
         _returns=SpyneArray(ValidationError))
    def validate_attrs(ctx, resource_attr_ids, scenario_id, template_id):
        errors = []
        error_dicts = template.validate_attrs(resource_attr_ids, scenario_id,
                                              template_id)
        for error_dict in error_dicts:
            error = ValidationError(
                ref_key=error_dict.get('ref_key'),
                ref_id=error_dict.get('ref_id'),
                ref_name=error_dict.get('ref_name'),
                resource_attr_id=error_dict.get('resource_attr_id'),
                attr_id=error_dict.get('attr_id'),
                attr_name=error_dict.get('attr_name'),
                dataset_id=error_dict.get('dataset_id'),
                scenario_id=error_dict.get('scenario_id'),
                template_id=error_dict.get('template_id'),
                error_text=error_dict.get('error_text'))
            errors.append(error)

        return errors

    @rpc(Integer, Integer, _returns=SpyneArray(ValidationError))
    def validate_scenario(ctx, scenario_id, template_id):
        errors = []
        error_dicts = template.validate_scenario(scenario_id, template_id)
        for error_dict in error_dicts:
            error = ValidationError(
                ref_key=error_dict.get('ref_key'),
                ref_id=error_dict.get('ref_id'),
                ref_name=error_dict.get('ref_name'),
                resource_attr_id=error_dict.get('resource_attr_id'),
                attr_id=error_dict.get('attr_id'),
                attr_name=error_dict.get('attr_name'),
                dataset_id=error_dict.get('dataset_id'),
                scenario_id=error_dict.get('scenario_id'),
                template_id=error_dict.get('template_id'),
                error_text=error_dict.get('error_text'))
            errors.append(error)

        return errors

    @rpc(Integer,
         Integer,
         Integer(min_occurs=0, max_occurs=1),
         _returns=SpyneArray(Unicode))
    def validate_network(ctx, network_id, template_id, scenario_id):
        errors = template.validate_network(network_id, template_id,
                                           scenario_id)
        return errors

    @rpc(Integer, Integer, _returns=SpyneArray(Unicode))
    def check_type_compatibility(ctx, type_1_id, type_2_id):
        errors = template.check_type_compatibility(type_1_id, type_2_id)
        return errors