Source code for pybel.io.web

# -*- coding: utf-8 -*-

"""This module facilitates rudimentary data exchange with `BEL Commons <https://bel-commons.scai.fraunhofer.de>`_."""

import logging
import os
from typing import Optional

import requests

from .nodelink import from_nodelink, to_nodelink
from ..config import config
from ..constants import DEFAULT_SERVICE_URL, PYBEL_REMOTE_HOST, PYBEL_REMOTE_PASSWORD, PYBEL_REMOTE_USER
from ..struct.graph import BELGraph
from ..version import get_version

__all__ = [
    'to_web',
    'from_web',
]

logger = logging.getLogger(__name__)

RECIEVE_ENDPOINT = '/api/receive/'
GET_ENDPOINT = '/api/network/{}/export/nodelink'


def _get_config_or_env(name: str) -> Optional[str]:
    return config.get(name) or os.environ.get(name)


def _get_host() -> str:
    """Find the host.

    Has three possibilities:

    1. The PyBEL config entry ``PYBEL_REMOTE_HOST``, loaded in :mod:`pybel.constants`
    2. The environment variable ``PYBEL_REMOTE_HOST``
    3. The default service URL, :data:`pybel.constants.DEFAULT_SERVICE_URL`
    """
    return _get_config_or_env(PYBEL_REMOTE_HOST) or DEFAULT_SERVICE_URL


def _get_user() -> Optional[str]:
    return _get_config_or_env(PYBEL_REMOTE_USER)


def _get_password() -> Optional[str]:
    return _get_config_or_env(PYBEL_REMOTE_PASSWORD)


[docs]def to_web( graph: BELGraph, host: Optional[str] = None, user: Optional[str] = None, password: Optional[str] = None, public: bool = False, ) -> requests.Response: """Send a graph to the receiver service and returns the :mod:`requests` response object. :param graph: A BEL graph :param host: The location of the BEL Commons server. Alternatively, looks up in PyBEL config with ``PYBEL_REMOTE_HOST`` or the environment as ``PYBEL_REMOTE_HOST`` Defaults to :data:`pybel.constants.DEFAULT_SERVICE_URL` :param user: Username for BEL Commons. Alternatively, looks up in PyBEL config with ``PYBEL_REMOTE_USER`` or the environment as ``PYBEL_REMOTE_USER`` :param password: Password for BEL Commons. Alternatively, looks up in PyBEL config with ``PYBEL_REMOTE_PASSWORD`` or the environment as ``PYBEL_REMOTE_PASSWORD`` :return: The response object from :mod:`requests` """ if host is None: host = _get_host() logger.debug('using host: %s', host) if user is None: user = _get_user() if user is None: raise ValueError('no user found') if password is None: password = _get_password() if password is None: raise ValueError('no password found') url = host.rstrip('/') + RECIEVE_ENDPOINT response = requests.post( url, json=to_nodelink(graph), headers={ 'content-type': 'application/json', 'User-Agent': 'PyBEL v{}'.format(get_version()), 'bel-commons-public': 'true' if public else 'false', }, auth=(user, password), ) logger.debug('received response: %s', response) return response
[docs]def from_web(network_id: int, host: Optional[str] = None) -> BELGraph: """Retrieve a public network from BEL Commons. In the future, this function may be extended to support authentication. :param network_id: The BEL Commons network identifier :param host: The location of the BEL Commons server. Alternatively, looks up in PyBEL config with ``PYBEL_REMOTE_HOST`` or the environment as ``PYBEL_REMOTE_HOST`` Defaults to :data:`pybel.constants.DEFAULT_SERVICE_URL` """ if host is None: host = _get_host() url = host + GET_ENDPOINT.format(network_id) res = requests.get(url) graph_json = res.json() graph = from_nodelink(graph_json) return graph