<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Aws methods module."""
import json

from hvac import exceptions, utils
from hvac.api.vault_api_base import VaultApiBase
from hvac.constants.aws import DEFAULT_MOUNT_POINT, ALLOWED_CREDS_ENDPOINTS, ALLOWED_CREDS_TYPES

class Aws(VaultApiBase):
    """AWS Secrets Engine (API).

    Reference: https://www.vaultproject.io/api/secret/aws/index.html
    """

    def configure_root_iam_credentials(self, access_key, secret_key, region=None, iam_endpoint=None, sts_endpoint=None,
                                       max_retries=None, mount_point=DEFAULT_MOUNT_POINT):
        """Configure the root IAM credentials to communicate with AWS.

        There are multiple ways to pass root IAM credentials to the Vault server, specified below with the highest
        precedence first. If credentials already exist, this will overwrite them.

        The official AWS SDK is used for sourcing credentials from env vars, shared files, or IAM/ECS instances.

            * Static credentials provided to the API as a payload
            * Credentials in the AWS_ACCESS_KEY, AWS_SECRET_KEY, and AWS_REGION environment variables on the server
            * Shared credentials files
            * Assigned IAM role or ECS task role credentials

        At present, this endpoint does not confirm that the provided AWS credentials are valid AWS credentials with
        proper permissions.

        Supported methods:
            POST: /{mount_point}/config/root. Produces: 204 (empty body)

        :param access_key: Specifies the AWS access key ID.
        :type access_key: str | unicode
        :param secret_key: Specifies the AWS secret access key.
        :type secret_key: str | unicode
        :param region: Specifies the AWS region. If not set it will use the AWS_REGION env var, AWS_DEFAULT_REGION env
            var, or us-east-1 in that order.
        :type region: str | unicode
        :param iam_endpoint: Specifies a custom HTTP IAM endpoint to use.
        :type iam_endpoint: str | unicode
        :param sts_endpoint: Specifies a custom HTTP STS endpoint to use.
        :type sts_endpoint: str | unicode
        :param max_retries: Number of max retries the client should use for recoverable errors. The default (-1) falls
            back to the AWS SDK's default behavior.
        :type max_retries: int
        :param mount_point: The "path" the method/backend was mounted on.
        :type mount_point: str | unicode
        :return: The response of the request.
        :rtype: requests.Response
        """
        params = {
            'access_key': access_key,
            'secret_key': secret_key,
            'max_retries': max_retries,
        }
        params.update(
            utils.remove_nones({
                'region': region,
                'iam_endpoint': iam_endpoint,
                'sts_endpoint': sts_endpoint,
            })
        )
        api_path = utils.format_url('/v1/{mount_point}/config/root', mount_point=mount_point)
        return self._adapter.post(
            url=api_path,
            json=params,
        )

    def rotate_root_iam_credentials(self, mount_point=DEFAULT_MOUNT_POINT):
        """Rotate static root IAM credentials.

        When you have configured Vault with static credentials, you can use this endpoint to have Vault rotate the
        access key it used. Note that, due to AWS eventual consistency, after calling this endpoint, subsequent calls
        from Vault to AWS may fail for a few seconds until AWS becomes consistent again.

        In order to call this endpoint, Vault's AWS access key MUST be the only access key on the IAM user; otherwise,
        generation of a new access key will fail. Once this method is called, Vault will now be the only entity that
        knows the AWS secret key is used to access AWS.

        Supported methods:
            POST: /{mount_point}/config/rotate-root. Produces: 200 application/json

        :return: The JSON response of the request.
        :rtype: dict
        """
        api_path = utils.format_url('/v1/{mount_point}/config/rotate-root', mount_point=mount_point)
        return self._adapter.post(
            url=api_path,
        )

    def configure_lease(self, lease, lease_max, mount_point=DEFAULT_MOUNT_POINT):
        """Configure lease settings for the AWS secrets engine.

        It is optional, as there are default values for lease and lease_max.

        Supported methods:
            POST: /{mount_point}/config/lease. Produces: 204 (empty body)

        :param lease: Specifies the lease value provided as a string duration with time suffix. "h" (hour) is the
            largest suffix.
        :type lease: str | unicode
        :param lease_max: Specifies the maximum lease value provided as a string duration with time suffix. "h" (hour)
            is the largest suffix.
        :type lease_max: str | unicode
        :param mount_point: The "path" the method/backend was mounted on.
        :type mount_point: str | unicode
        :return: The response of the request.
        :rtype: requests.Response
        """
        params = {
            'lease': lease,
            'lease_max': lease_max,
        }
        api_path = utils.format_url('/v1/{mount_point}/config/lease', mount_point=mount_point)
        return self._adapter.post(
            url=api_path,
            json=params,
        )

    def read_lease_config(self, mount_point=DEFAULT_MOUNT_POINT):
        """Read the current lease settings for the AWS secrets engine.

        Supported methods:
            GET: /{mount_point}/config/lease. Produces: 200 application/json

        :param mount_point: The "path" the method/backend was mounted on.
        :type mount_point: str | unicode
        :return: The JSON response of the request.
        :rtype: dict
        """
        api_path = utils.format_url('/v1/{mount_point}/config/lease', mount_point=mount_point)
        return self._adapter.get(
            url=api_path,
        )

    def create_or_update_role(self, name, credential_type, policy_document=None, default_sts_ttl=None, max_sts_ttl=None,
                              role_arns=None, policy_arns=None, legacy_params=False, mount_point=DEFAULT_MOUNT_POINT,
                              iam_tags=None):
        """Create or update the role with the given name.

        If a role with the name does not exist, it will be created. If the role exists, it will be updated with the new
        attributes.

        Supported methods:
            POST: /{mount_point}/roles/{name}. Produces: 204 (empty body)

        :param name: Specifies the name of the role to create. This is part of the request URL.
        :type name: str | unicode
        :param credential_type: Specifies the type of credential to be used when retrieving credentials from the role.
            Must be one of iam_user, assumed_role, or federation_token.
        :type credential_type: str | unicode
        :param policy_document: The IAM policy document for the role. The behavior depends on the credential type. With
            iam_user, the policy document will be attached to the IAM user generated and augment the permissions the IAM
            user has. With assumed_role and federation_token, the policy document will act as a filter on what the
            credentials can do.
        :type policy_document: dict | str | unicode
        :param default_sts_ttl: The default TTL for STS credentials. When a TTL is not specified when STS credentials
            are requested, and a default TTL is specified on the role, then this default TTL will be used. Valid only
            when credential_type is one of assumed_role or federation_token.
        :type default_sts_ttl: str | unicode
        :param max_sts_ttl: The max allowed TTL for STS credentials (credentials TTL are capped to max_sts_ttl). Valid
            only when credential_type is one of assumed_role or federation_token.
        :type max_sts_ttl: str | unicode
        :param role_arns: Specifies the ARNs of the AWS roles this Vault role is allowed to assume. Required when
            credential_type is assumed_role and prohibited otherwise. This is a comma-separated string or JSON array.
            String types supported for Vault legacy parameters.
        :type role_arns: list | str | unicode
        :param policy_arns: Specifies the ARNs of the AWS managed policies to be attached to IAM users when they are
            requested. Valid only when credential_type is iam_user. When credential_type is iam_user, at least one of
            policy_arns or policy_document must be specified. This is a comma-separated string or JSON array.
        :type policy_arns: list
        :param legacy_params: Flag to send legacy (Vault versions < 0.11.0) parameters in the request. When this is set
            to True, policy_document and policy_arns are the only parameters used from this method.
        :type legacy_params: bool
        :param mount_point: The "path" the method/backend was mounted on.
        :type mount_point: str | unicode
        :param iam_tags: A list of strings representing a key/value pair to be used for any IAM user that is created by
            this role. Format is a key and value separated by an =.
        :type iam_tags: list
        :return: The response of the request.
        :rtype: requests.Response
        """
        if credential_type not in ALLOWED_CREDS_TYPES:
            error_msg = 'invalid credential_type argument provided "{arg}", supported types: "{allowed_types}"'
            raise exceptions.ParamValidationError(error_msg.format(
                arg=credential_type,
                allowed_types=', '.join(ALLOWED_CREDS_TYPES),
            ))
        if isinstance(policy_document, dict):
            policy_document = json.dumps(policy_document, indent=4, sort_keys=True)

        if legacy_params:
            # Support for Vault <0.11.0
            params = {
                'policy': policy_document,
                'arn': policy_arns[0] if isinstance(policy_arns, list) else policy_arns,
            }
        else:
            params = {
                'credential_type': credential_type,
            }
            params.update(
                utils.remove_nones({
                    'policy_document': policy_document,
                    'default_sts_ttl': default_sts_ttl,
                    'max_sts_ttl': max_sts_ttl,
                    'role_arns': role_arns,
                    'policy_arns': policy_arns,
                    'iam_tags': iam_tags,
                })
            )
        api_path = utils.format_url(
            '/v1/{mount_point}/roles/{name}',
            mount_point=mount_point,
            name=name,
        )
        return self._adapter.post(
            url=api_path,
            json=params,
        )

    def read_role(self, name, mount_point=DEFAULT_MOUNT_POINT):
        """Query an existing role by the given name.

        If the role does not exist, a 404 is returned.

        Supported methods:
            GET: /{mount_point}/roles/{name}. Produces: 200 application/json

        :param name: Specifies the name of the role to read. This is part of the request URL.
        :type name: str | unicode
        :param mount_point: The "path" the method/backend was mounted on.
        :type mount_point: str | unicode
        :return: The JSON response of the request.
        :rtype: dict
        """
        api_path = utils.format_url(
            '/v1/{mount_point}/roles/{name}',
            mount_point=mount_point,
            name=name,
        )
        return self._adapter.get(
            url=api_path,
        )

    def list_roles(self, mount_point=DEFAULT_MOUNT_POINT):
        """List all existing roles in the secrets engine.

        Supported methods:
            LIST: /{mount_point}/roles. Produces: 200 application/json

        :param mount_point: The "path" the method/backend was mounted on.
        :type mount_point: str | unicode
        :return: The JSON response of the request.
        :rtype: dict
        """
        api_path = utils.format_url('/v1/{mount_point}/roles', mount_point=mount_point)
        return self._adapter.list(
            url=api_path,
        )

    def delete_role(self, name, mount_point=DEFAULT_MOUNT_POINT):
        """Delete an existing role by the given name.

        If the role does not exist, a 404 is returned.

        Supported methods:
            DELETE: /{mount_point}/roles/{name}. Produces: 204 (empty body)

        :param name: the name of the role to delete. This
            is part of the request URL.
        :type name: str | unicode
        :param mount_point: The "path" the method/backend was mounted on.
        :type mount_point: str | unicode
        :return: The response of the request.
        :rtype: requests.Response
        """
        api_path = utils.format_url(
            '/v1/{mount_point}/roles/{name}',
            mount_point=mount_point,
            name=name,
        )
        return self._adapter.delete(
            url=api_path,
        )

    def generate_credentials(self, name, role_arn=None, ttl=None, endpoint='creds', mount_point=DEFAULT_MOUNT_POINT):
        """Generates credential based on the named role.

        This role must be created before queried.

        The /aws/creds and /aws/sts endpoints are almost identical. The exception is when retrieving credentials for a
        role that was specified with the legacy arn or policy parameter. In this case, credentials retrieved through
        /aws/sts must be of either the assumed_role or federation_token types, and credentials retrieved through
        /aws/creds must be of the iam_user type.

        :param name: Specifies the name of the role to generate credentials against. This is part of the request URL.
        :type name: str | unicode
        :param role_arn: The ARN of the role to assume if credential_type on the Vault role is assumed_role. Must match
            one of the allowed role ARNs in the Vault role. Optional if the Vault role only allows a single AWS role
            ARN; required otherwise.
        :type role_arn: str | unicode
        :param ttl: Specifies the TTL for the use of the STS token. This is specified as a string with a duration
            suffix. Valid only when credential_type is assumed_role or federation_token. When not specified, the default
            sts_ttl set for the role will be used. If that is also not set, then the default value of 3600s will be
            used. AWS places limits on the maximum TTL allowed. See the AWS documentation on the DurationSeconds
            parameter for AssumeRole (for assumed_role credential types) and GetFederationToken (for federation_token
            credential types) for more details.
        :type ttl: str | unicode
        :param endpoint: Supported endpoints:
            GET: /{mount_point}/creds/{name}. Produces: 200 application/json
            GET: /{mount_point}/sts/{name}. Produces: 200 application/json
        :type endpoint: str | unicode
        :param mount_point: The "path" the method/backend was mounted on.
        :type mount_point: str | unicode
        :return: The JSON response of the request.
        :rtype: dict
        """
        if endpoint not in ALLOWED_CREDS_ENDPOINTS:
            error_msg = 'invalid endpoint argument provided "{arg}", supported types: "{allowed_endpoints}"'
            raise exceptions.ParamValidationError(error_msg.format(
                arg=endpoint,
                allowed_endpoints=', '.join(ALLOWED_CREDS_ENDPOINTS),
            ))
        params = {
            'name': name,
        }
        params.update(
            utils.remove_nones({
                'role_arn': role_arn,
                'ttl': ttl,
            })
        )
        api_path = utils.format_url(
            '/v1/{mount_point}/{endpoint}/{name}',
            mount_point=mount_point,
            endpoint=endpoint,
            name=name,
        )

        return self._adapter.get(
            url=api_path,
            params=params,
        )
<commit_msg>Swap position of iam_tags and mount_point params<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Aws methods module."""
import json

from hvac import exceptions, utils
from hvac.api.vault_api_base import VaultApiBase
from hvac.constants.aws import DEFAULT_MOUNT_POINT, ALLOWED_CREDS_ENDPOINTS, ALLOWED_CREDS_TYPES

class Aws(VaultApiBase):
    """AWS Secrets Engine (API).

    Reference: https://www.vaultproject.io/api/secret/aws/index.html
    """

    def configure_root_iam_credentials(self, access_key, secret_key, region=None, iam_endpoint=None, sts_endpoint=None,
                                       max_retries=None, mount_point=DEFAULT_MOUNT_POINT):
        """Configure the root IAM credentials to communicate with AWS.

        There are multiple ways to pass root IAM credentials to the Vault server, specified below with the highest
        precedence first. If credentials already exist, this will overwrite them.

        The official AWS SDK is used for sourcing credentials from env vars, shared files, or IAM/ECS instances.

            * Static credentials provided to the API as a payload
            * Credentials in the AWS_ACCESS_KEY, AWS_SECRET_KEY, and AWS_REGION environment variables on the server
            * Shared credentials files
            * Assigned IAM role or ECS task role credentials

        At present, this endpoint does not confirm that the provided AWS credentials are valid AWS credentials with
        proper permissions.

        Supported methods:
            POST: /{mount_point}/config/root. Produces: 204 (empty body)

        :param access_key: Specifies the AWS access key ID.
        :type access_key: str | unicode
        :param secret_key: Specifies the AWS secret access key.
        :type secret_key: str | unicode
        :param region: Specifies the AWS region. If not set it will use the AWS_REGION env var, AWS_DEFAULT_REGION env
            var, or us-east-1 in that order.
        :type region: str | unicode
        :param iam_endpoint: Specifies a custom HTTP IAM endpoint to use.
        :type iam_endpoint: str | unicode
        :param sts_endpoint: Specifies a custom HTTP STS endpoint to use.
        :type sts_endpoint: str | unicode
        :param max_retries: Number of max retries the client should use for recoverable errors. The default (-1) falls
            back to the AWS SDK's default behavior.
        :type max_retries: int
        :param mount_point: The "path" the method/backend was mounted on.
        :type mount_point: str | unicode
        :return: The response of the request.
        :rtype: requests.Response
        """
        params = {
            'access_key': access_key,
            'secret_key': secret_key,
            'max_retries': max_retries,
        }
        params.update(
            utils.remove_nones({
                'region': region,
                'iam_endpoint': iam_endpoint,
                'sts_endpoint': sts_endpoint,
            })
        )
        api_path = utils.format_url('/v1/{mount_point}/config/root', mount_point=mount_point)
        return self._adapter.post(
            url=api_path,
            json=params,
        )

    def rotate_root_iam_credentials(self, mount_point=DEFAULT_MOUNT_POINT):
        """Rotate static root IAM credentials.

        When you have configured Vault with static credentials, you can use this endpoint to have Vault rotate the
        access key it used. Note that, due to AWS eventual consistency, after calling this endpoint, subsequent calls
        from Vault to AWS may fail for a few seconds until AWS becomes consistent again.

        In order to call this endpoint, Vault's AWS access key MUST be the only access key on the IAM user; otherwise,
        generation of a new access key will fail. Once this method is called, Vault will now be the only entity that
        knows the AWS secret key is used to access AWS.

        Supported methods:
            POST: /{mount_point}/config/rotate-root. Produces: 200 application/json

        :return: The JSON response of the request.
        :rtype: dict
        """
        api_path = utils.format_url('/v1/{mount_point}/config/rotate-root', mount_point=mount_point)
        return self._adapter.post(
            url=api_path,
        )

    def configure_lease(self, lease, lease_max, mount_point=DEFAULT_MOUNT_POINT):
        """Configure lease settings for the AWS secrets engine.

        It is optional, as there are default values for lease and lease_max.

        Supported methods:
            POST: /{mount_point}/config/lease. Produces: 204 (empty body)

        :param lease: Specifies the lease value provided as a string duration with time suffix. "h" (hour) is the
            largest suffix.
        :type lease: str | unicode
        :param lease_max: Specifies the maximum lease value provided as a string duration with time suffix. "h" (hour)
            is the largest suffix.
        :type lease_max: str | unicode
        :param mount_point: The "path" the method/backend was mounted on.
        :type mount_point: str | unicode
        :return: The response of the request.
        :rtype: requests.Response
        """
        params = {
            'lease': lease,
            'lease_max': lease_max,
        }
        api_path = utils.format_url('/v1/{mount_point}/config/lease', mount_point=mount_point)
        return self._adapter.post(
            url=api_path,
            json=params,
        )

    def read_lease_config(self, mount_point=DEFAULT_MOUNT_POINT):
        """Read the current lease settings for the AWS secrets engine.

        Supported methods:
            GET: /{mount_point}/config/lease. Produces: 200 application/json

        :param mount_point: The "path" the method/backend was mounted on.
        :type mount_point: str | unicode
        :return: The JSON response of the request.
        :rtype: dict
        """
        api_path = utils.format_url('/v1/{mount_point}/config/lease', mount_point=mount_point)
        return self._adapter.get(
            url=api_path,
        )

    def create_or_update_role(self, name, credential_type, policy_document=None, default_sts_ttl=None, max_sts_ttl=None,
                              role_arns=None, policy_arns=None, legacy_params=False, iam_tags=None, mount_point=DEFAULT_MOUNT_POINT):
        """Create or update the role with the given name.

        If a role with the name does not exist, it will be created. If the role exists, it will be updated with the new
        attributes.

        Supported methods:
            POST: /{mount_point}/roles/{name}. Produces: 204 (empty body)

        :param name: Specifies the name of the role to create. This is part of the request URL.
        :type name: str | unicode
        :param credential_type: Specifies the type of credential to be used when retrieving credentials from the role.
            Must be one of iam_user, assumed_role, or federation_token.
        :type credential_type: str | unicode
        :param policy_document: The IAM policy document for the role. The behavior depends on the credential type. With
            iam_user, the policy document will be attached to the IAM user generated and augment the permissions the IAM
            user has. With assumed_role and federation_token, the policy document will act as a filter on what the
            credentials can do.
        :type policy_document: dict | str | unicode
        :param default_sts_ttl: The default TTL for STS credentials. When a TTL is not specified when STS credentials
            are requested, and a default TTL is specified on the role, then this default TTL will be used. Valid only
            when credential_type is one of assumed_role or federation_token.
        :type default_sts_ttl: str | unicode
        :param max_sts_ttl: The max allowed TTL for STS credentials (credentials TTL are capped to max_sts_ttl). Valid
            only when credential_type is one of assumed_role or federation_token.
        :type max_sts_ttl: str | unicode
        :param role_arns: Specifies the ARNs of the AWS roles this Vault role is allowed to assume. Required when
            credential_type is assumed_role and prohibited otherwise. This is a comma-separated string or JSON array.
            String types supported for Vault legacy parameters.
        :type role_arns: list | str | unicode
        :param policy_arns: Specifies the ARNs of the AWS managed policies to be attached to IAM users when they are
            requested. Valid only when credential_type is iam_user. When credential_type is iam_user, at least one of
            policy_arns or policy_document must be specified. This is a comma-separated string or JSON array.
        :type policy_arns: list
        :param legacy_params: Flag to send legacy (Vault versions < 0.11.0) parameters in the request. When this is set
            to True, policy_document and policy_arns are the only parameters used from this method.
        :type legacy_params: bool
        :param iam_tags: A list of strings representing a key/value pair to be used for any IAM user that is created by
            this role. Format is a key and value separated by an =.
        :type iam_tags: list
        :param mount_point: The "path" the method/backend was mounted on.
        :type mount_point: str | unicode
        :return: The response of the request.
        :rtype: requests.Response
        """
        if credential_type not in ALLOWED_CREDS_TYPES:
            error_msg = 'invalid credential_type argument provided "{arg}", supported types: "{allowed_types}"'
            raise exceptions.ParamValidationError(error_msg.format(
                arg=credential_type,
                allowed_types=', '.join(ALLOWED_CREDS_TYPES),
            ))
        if isinstance(policy_document, dict):
            policy_document = json.dumps(policy_document, indent=4, sort_keys=True)

        if legacy_params:
            # Support for Vault <0.11.0
            params = {
                'policy': policy_document,
                'arn': policy_arns[0] if isinstance(policy_arns, list) else policy_arns,
            }
        else:
            params = {
                'credential_type': credential_type,
            }
            params.update(
                utils.remove_nones({
                    'policy_document': policy_document,
                    'default_sts_ttl': default_sts_ttl,
                    'max_sts_ttl': max_sts_ttl,
                    'role_arns': role_arns,
                    'policy_arns': policy_arns,
                    'iam_tags': iam_tags,
                })
            )
        api_path = utils.format_url(
            '/v1/{mount_point}/roles/{name}',
            mount_point=mount_point,
            name=name,
        )
        return self._adapter.post(
            url=api_path,
            json=params,
        )

    def read_role(self, name, mount_point=DEFAULT_MOUNT_POINT):
        """Query an existing role by the given name.

        If the role does not exist, a 404 is returned.

        Supported methods:
            GET: /{mount_point}/roles/{name}. Produces: 200 application/json

        :param name: Specifies the name of the role to read. This is part of the request URL.
        :type name: str | unicode
        :param mount_point: The "path" the method/backend was mounted on.
        :type mount_point: str | unicode
        :return: The JSON response of the request.
        :rtype: dict
        """
        api_path = utils.format_url(
            '/v1/{mount_point}/roles/{name}',
            mount_point=mount_point,
            name=name,
        )
        return self._adapter.get(
            url=api_path,
        )

    def list_roles(self, mount_point=DEFAULT_MOUNT_POINT):
        """List all existing roles in the secrets engine.

        Supported methods:
            LIST: /{mount_point}/roles. Produces: 200 application/json

        :param mount_point: The "path" the method/backend was mounted on.
        :type mount_point: str | unicode
        :return: The JSON response of the request.
        :rtype: dict
        """
        api_path = utils.format_url('/v1/{mount_point}/roles', mount_point=mount_point)
        return self._adapter.list(
            url=api_path,
        )

    def delete_role(self, name, mount_point=DEFAULT_MOUNT_POINT):
        """Delete an existing role by the given name.

        If the role does not exist, a 404 is returned.

        Supported methods:
            DELETE: /{mount_point}/roles/{name}. Produces: 204 (empty body)

        :param name: the name of the role to delete. This
            is part of the request URL.
        :type name: str | unicode
        :param mount_point: The "path" the method/backend was mounted on.
        :type mount_point: str | unicode
        :return: The response of the request.
        :rtype: requests.Response
        """
        api_path = utils.format_url(
            '/v1/{mount_point}/roles/{name}',
            mount_point=mount_point,
            name=name,
        )
        return self._adapter.delete(
            url=api_path,
        )

    def generate_credentials(self, name, role_arn=None, ttl=None, endpoint='creds', mount_point=DEFAULT_MOUNT_POINT):
        """Generates credential based on the named role.

        This role must be created before queried.

        The /aws/creds and /aws/sts endpoints are almost identical. The exception is when retrieving credentials for a
        role that was specified with the legacy arn or policy parameter. In this case, credentials retrieved through
        /aws/sts must be of either the assumed_role or federation_token types, and credentials retrieved through
        /aws/creds must be of the iam_user type.

        :param name: Specifies the name of the role to generate credentials against. This is part of the request URL.
        :type name: str | unicode
        :param role_arn: The ARN of the role to assume if credential_type on the Vault role is assumed_role. Must match
            one of the allowed role ARNs in the Vault role. Optional if the Vault role only allows a single AWS role
            ARN; required otherwise.
        :type role_arn: str | unicode
        :param ttl: Specifies the TTL for the use of the STS token. This is specified as a string with a duration
            suffix. Valid only when credential_type is assumed_role or federation_token. When not specified, the default
            sts_ttl set for the role will be used. If that is also not set, then the default value of 3600s will be
            used. AWS places limits on the maximum TTL allowed. See the AWS documentation on the DurationSeconds
            parameter for AssumeRole (for assumed_role credential types) and GetFederationToken (for federation_token
            credential types) for more details.
        :type ttl: str | unicode
        :param endpoint: Supported endpoints:
            GET: /{mount_point}/creds/{name}. Produces: 200 application/json
            GET: /{mount_point}/sts/{name}. Produces: 200 application/json
        :type endpoint: str | unicode
        :param mount_point: The "path" the method/backend was mounted on.
        :type mount_point: str | unicode
        :return: The JSON response of the request.
        :rtype: dict
        """
        if endpoint not in ALLOWED_CREDS_ENDPOINTS:
            error_msg = 'invalid endpoint argument provided "{arg}", supported types: "{allowed_endpoints}"'
            raise exceptions.ParamValidationError(error_msg.format(
                arg=endpoint,
                allowed_endpoints=', '.join(ALLOWED_CREDS_ENDPOINTS),
            ))
        params = {
            'name': name,
        }
        params.update(
            utils.remove_nones({
                'role_arn': role_arn,
                'ttl': ttl,
            })
        )
        api_path = utils.format_url(
            '/v1/{mount_point}/{endpoint}/{name}',
            mount_point=mount_point,
            endpoint=endpoint,
            name=name,
        )

        return self._adapter.get(
            url=api_path,
            params=params,
        )
<|endoftext|>


<commit_before>""" Example for scatter plot visualization of sources """

import numpy as np
import matplotlib.pyplot as plt
import sfs

# simulation parameters
pw_angle = 45  # traveling direction of plane wave
f = 300  # frequency
amplitude = 70000
t = 0.002

# angular frequency
omega = 2 * np.pi * f
# normal vector of plane wave
npw = sfs.util.direction_vector(np.radians(pw_angle), np.radians(90))

#grid = sfs.util.xyz_grid([-2, 2], [-2, 2], 0, spacing=0.5)

x = np.linspace(-2, 2, num=50)
y = np.linspace(-2, 2, num=50)
grid = sfs.util.asarray_of_arrays( np.meshgrid(x, y) + [0])

#x = np.random.uniform(-2, 2, 5000)
#y = np.random.uniform(-2, 2, 5000)
#grid = sfs.util.asarray_of_arrays( [x, y] + [0])

#grid = sfs.util.xyz_grid(1, 1, 0, spacing=0.2)

vx, vy, vz = sfs.mono.source.plane_velocity(omega, 0, npw, grid)

# visualization
grid = sfs.util.asarray_of_arrays(grid[:-1])

#gridx, gridy = grid[:2]
#grid = sfs.util.asarray_of_arrays([gridx[:2], gridy[:2]])

v = sfs.util.asarray_of_arrays([vx, vy])

v = sfs.mono.synthesized.shiftphase(v, omega*t)
d = grid + amplitude * sfs.util.displacement(v, omega)

plt.figure(figsize=(10, 10))
sfs.plot.particles(d)
plt.axis('tight')
<commit_msg>Combined plot of pressure distribution and particle displacement<commit_after>""" Example for scatter plot visualization of sources """

import numpy as np
import matplotlib.pyplot as plt
import sfs

# simulation parameters
pw_angle = 45  # traveling direction of plane wave
f = 300  # frequency
amplitude = 90000
t = 0.000

# angular frequency
omega = 2 * np.pi * f
# normal vector of plane wave
npw = sfs.util.direction_vector(np.radians(pw_angle), np.radians(90))

# sfs grid object
#grid = sfs.util.xyz_grid([-2, 2], [-2, 2], 0, spacing=0.5)

# lineary spaced grid
x = np.linspace(-2, 2, num=50)
y = np.linspace(-2, 2, num=50)
grid = sfs.util.asarray_of_arrays( np.meshgrid(x, y) + [0])

# random grid
#x = np.random.uniform(-2, 2, 4000)
#y = np.random.uniform(-2, 2, 4000)
#grid = sfs.util.asarray_of_arrays( [x, y] + [0])

# compute velocity and pressure field
vx, vy, vz = sfs.mono.source.plane_velocity(omega, 0, npw, grid)
p = sfs.mono.source.plane(omega, 0, npw, grid)

# compute and plot displacement
grid = sfs.util.asarray_of_arrays(grid[:-1])

#gridx, gridy = grid[:2]
#grid = sfs.util.asarray_of_arrays([gridx[:2], gridy[:2]])

v = sfs.util.asarray_of_arrays([vx, vy])
v = sfs.mono.synthesized.shiftphase(v, omega*t)
X = grid + amplitude * sfs.util.displacement(v, omega)

fig, ax = plt.subplots(figsize=(10, 10))

sfs.plot.soundfield(p, grid, ax=ax)
sfs.plot.particles(X, ax=ax, c=u'k', alpha=.7)
plt.axis('off')
<|endoftext|>


<commit_before>#BEGIN_HEADER
# The header block is where all import statments should live
import sys
import traceback
import uuid
import json
from pprint import pprint, pformat
from biokbase.workspace.client import Workspace as workspaceService
#END_HEADER

class HomologySearch:
    '''
    Module Name:
    HomologySearch

    Module Description:
    A KBase module: HomologySearch
    '''

    ######## WARNING FOR GEVENT USERS #######
    # Since asynchronous IO can lead to methods - even the same method -
    # interrupting each other, you must be *very* careful when using global
    # state. A method could easily clobber the state set by another while
    # the latter method is running.
    #########################################
    #BEGIN_CLASS_HEADER
    # Class variables and functions can be defined in this block
    workspaceURL = None
    #END_CLASS_HEADER

    # config contains contents of config file in a hash or None if it couldn't
    # be found
    def __init__(self, config):
        #BEGIN_CONSTRUCTOR
        # self.workspaceURL = config['workspace-url']
        #END_CONSTRUCTOR
        pass

    def blast_fasta(self, ctx, params):
        # ctx is the context object
        # return variables are: output
        #BEGIN blast_fasta

        print('Starting blast_fasta')

        # Step 1 - parse parameters
        # if 'sequence' not in params:
        #     raise ValueError('Parameter sequence is not set in input arguments')
        # if 'search_type' not in params:
        #     raise ValueError('Parameter search type is not set in input arguments')
        # if 'program' not in params:
        #     raise ValueError('Parameter program is not set in input arguments')

        # Step 2 - query

        # Step 3 - wrap results
        queryReturn = '{"result":[[{"report":{"search_target":{"db":"/vol/patric3/kbase/blastdb/genomes/kb|g.0.faa"},"params":{"gap_open":11,"gap_extend":1,"cbs":2,"expect":1e-05,"filter":"F","matrix":"BLOSUM62"},"results":{"search":{"hits":[{"len":428,"description":[{"accession":"3656","title":"kb|g.0.peg.4288   Threonine synthase (EC 4.2.3.1)   [Escherichia coli K12]","id":"kb|g.0.peg.4288"}],"num":1,"hsps":[{"identity":428,"qseq":"MKLYNLKDHNEQVSFAQAVTQGLGKNQGLFFPHDLPEFSLTEIDEMLKLDFVTRSAKILSAFIGDEIPQEILEERVRAAFAFPAPVANVESDVGCLELFHGPTLAFKDFGGRFMAQMLTHIAGDKPVTILTATSGDTGAAVAHAFYGLPNVKVVILYPRGKISPLQEKLFCTLGGNIETVAIDGDFDACQALVKQAFDDEELKVALGLNSANSINISRLLAQICYYFEAVAQLPQETRNQLVVSVPSGNFGDLTAGLLAKSLGLPVKRFIAATNVNDTVPRFLHDGQWSPKATQATLSNAMDVSQPNNWPRVEELFRRKIWQLKELGYAAVDDETTQQTMRELKELGYTSEPHAAVAYRALRDQLNPGEYGLFLGTAHPAKFKESVEAILGETLDLPKELAERADLPLLSHNLPADFAALRKLMMNHQ","hit_to":428,"hit_from":1,"positive":428,"bit_score":882.093,"score":2278,"midline":"MKLYNLKDHNEQVSFAQAVTQGLGKNQGLFFPHDLPEFSLTEIDEMLKLDFVTRSAKILSAFIGDEIPQEILEERVRAAFAFPAPVANVESDVGCLELFHGPTLAFKDFGGRFMAQMLTHIAGDKPVTILTATSGDTGAAVAHAFYGLPNVKVVILYPRGKISPLQEKLFCTLGGNIETVAIDGDFDACQALVKQAFDDEELKVALGLNSANSINISRLLAQICYYFEAVAQLPQETRNQLVVSVPSGNFGDLTAGLLAKSLGLPVKRFIAATNVNDTVPRFLHDGQWSPKATQATLSNAMDVSQPNNWPRVEELFRRKIWQLKELGYAAVDDETTQQTMRELKELGYTSEPHAAVAYRALRDQLNPGEYGLFLGTAHPAKFKESVEAILGETLDLPKELAERADLPLLSHNLPADFAALRKLMMNHQ","gaps":0,"evalue":0,"query_to":428,"query_from":1,"hseq":"MKLYNLKDHNEQVSFAQAVTQGLGKNQGLFFPHDLPEFSLTEIDEMLKLDFVTRSAKILSAFIGDEIPQEILEERVRAAFAFPAPVANVESDVGCLELFHGPTLAFKDFGGRFMAQMLTHIAGDKPVTILTATSGDTGAAVAHAFYGLPNVKVVILYPRGKISPLQEKLFCTLGGNIETVAIDGDFDACQALVKQAFDDEELKVALGLNSANSINISRLLAQICYYFEAVAQLPQETRNQLVVSVPSGNFGDLTAGLLAKSLGLPVKRFIAATNVNDTVPRFLHDGQWSPKATQATLSNAMDVSQPNNWPRVEELFRRKIWQLKELGYAAVDDETTQQTMRELKELGYTSEPHAAVAYRALRDQLNPGEYGLFLGTAHPAKFKESVEAILGETLDLPKELAERADLPLLSHNLPADFAALRKLMMNHQ","num":1,"align_len":428}]}],"query_title":"fig|83333.1.peg.4","query_len":428,"query_id":"fig|83333.1.peg.4","stat":{"lambda":0.267,"hsp_len":86,"kappa":0.041,"entropy":0.14,"db_num":4309,"eff_space":335033460,"db_len":1350204}}},"version":"BLASTP 2.3.0+","program":"blastp","reference":"Stephen F. Altschul, Thomas L. Madden, Alejandro A. Schäffer, Jinghui Zhang, Zheng Zhang, Webb Miller, and David J. Lipman (1997), \"Gapped BLAST and PSI-BLAST: a new generation of protein database search programs\", Nucleic Acids Res. 25:3389-3402."}}],{"kb|g.0.peg.4288":{"genome_name":"Escherichia coli K12","function":"Threonine synthase (EC 4.2.3.1)","genome_id":"kb|g.0"}}],"id":"8527913568541408","version":"1.1"}';
        output = {'json_output': queryReturn}
        # jsonQueryReturn = json.loads(queryReturn)

        returnVal = {
            'BlastOutput_db': '',
            'BlastOutput_program': '',
            'BlastOutput_query-ID': '',
            'BlastOutput_query-def': '',
            'BlastOutput_query-len': '',
            'BlastOutput_reference': '',
            'BlastOutput_version': '',
            'BlastOutput_param': {
                'Parameters': {
                    'Parameters_expect': '',
                    'Parameters_filter': '',
                    'Parameters_gap-extend': '',
                    'Parameters_gap-open': '',
                    'Parameters_matrix': '',
                    'Parameters_sc-match': '',
                    'Parameters_sc-mismatch': ''
                }
            },
            'BlastOutput_iterations': {
                'Iteration': [
                    {
                        'Iteration_hits': {
                            'Hit': [
                                {
                                    'Hit_accession': '',
                                    'Hit_def': '',
                                    'Hit_id': '',
                                    'Hit_len': '',
                                    'Hit_num': '',
                                    'Hit_hsps': {
                                        'Hsp': [
                                            {
                                                'Hsp_align-len': '',
                                                'Hsp_bit-score': '',
                                                'Hsp_evalue': '',
                                                'Hsp_hit-frame': '',
                                                'Hsp_hit-from': '',
                                                'Hsp_hit-to': '',
                                                'Hsp_hseq': '',
                                                'Hsp_identity': '',
                                                'Hsp_midline': '',
                                                'Hsp_num': '',
                                                'Hsp_positive': '',
                                                'Hsp_qseq': '',
                                                'Hsp_query-frame': '',
                                                'Hsp_query-from': '',
                                                'Hsp_query-to': '',
                                                'Hsp_score': ''
                                            }
                                        ]
                                    }
                                }
                            ]
                        },
                        'Iteration_iter-num': '',
                        'Iteration_query-ID': '',
                        'Iteration_query-def': '',
                        'Iteration_query-len': ''
                    }
                ]
            }
        }
        #END blast_fasta

        # At some point might do deeper type checking...
        if not isinstance(output, dict):
            raise ValueError('Method blast_fasta return value ' +
                             'output is not type dict as required.')
        # return the results
        return [output]
<commit_msg>print for debugging<commit_after>#BEGIN_HEADER
# The header block is where all import statments should live
import sys
import traceback
import uuid
import json
from pprint import pprint, pformat
from biokbase.workspace.client import Workspace as workspaceService
#END_HEADER

class HomologySearch:
    '''
    Module Name:
    HomologySearch

    Module Description:
    A KBase module: HomologySearch
    '''

    ######## WARNING FOR GEVENT USERS #######
    # Since asynchronous IO can lead to methods - even the same method -
    # interrupting each other, you must be *very* careful when using global
    # state. A method could easily clobber the state set by another while
    # the latter method is running.
    #########################################
    #BEGIN_CLASS_HEADER
    # Class variables and functions can be defined in this block
    workspaceURL = None
    #END_CLASS_HEADER

    # config contains contents of config file in a hash or None if it couldn't
    # be found
    def __init__(self, config):
        #BEGIN_CONSTRUCTOR
        # self.workspaceURL = config['workspace-url']
        #END_CONSTRUCTOR
        pass

    def blast_fasta(self, ctx, params):
        # ctx is the context object
        # return variables are: output
        #BEGIN blast_fasta

        print('Starting blast_fasta')

        # Step 1 - parse parameters
        # if 'sequence' not in params:
        #     raise ValueError('Parameter sequence is not set in input arguments')
        # if 'search_type' not in params:
        #     raise ValueError('Parameter search type is not set in input arguments')
        # if 'program' not in params:
        #     raise ValueError('Parameter program is not set in input arguments')

        # Step 2 - query

        # Step 3 - wrap results
        queryReturn = '{"result":[[{"report":{"search_target":{"db":"/vol/patric3/kbase/blastdb/genomes/kb|g.0.faa"},"params":{"gap_open":11,"gap_extend":1,"cbs":2,"expect":1e-05,"filter":"F","matrix":"BLOSUM62"},"results":{"search":{"hits":[{"len":428,"description":[{"accession":"3656","title":"kb|g.0.peg.4288   Threonine synthase (EC 4.2.3.1)   [Escherichia coli K12]","id":"kb|g.0.peg.4288"}],"num":1,"hsps":[{"identity":428,"qseq":"MKLYNLKDHNEQVSFAQAVTQGLGKNQGLFFPHDLPEFSLTEIDEMLKLDFVTRSAKILSAFIGDEIPQEILEERVRAAFAFPAPVANVESDVGCLELFHGPTLAFKDFGGRFMAQMLTHIAGDKPVTILTATSGDTGAAVAHAFYGLPNVKVVILYPRGKISPLQEKLFCTLGGNIETVAIDGDFDACQALVKQAFDDEELKVALGLNSANSINISRLLAQICYYFEAVAQLPQETRNQLVVSVPSGNFGDLTAGLLAKSLGLPVKRFIAATNVNDTVPRFLHDGQWSPKATQATLSNAMDVSQPNNWPRVEELFRRKIWQLKELGYAAVDDETTQQTMRELKELGYTSEPHAAVAYRALRDQLNPGEYGLFLGTAHPAKFKESVEAILGETLDLPKELAERADLPLLSHNLPADFAALRKLMMNHQ","hit_to":428,"hit_from":1,"positive":428,"bit_score":882.093,"score":2278,"midline":"MKLYNLKDHNEQVSFAQAVTQGLGKNQGLFFPHDLPEFSLTEIDEMLKLDFVTRSAKILSAFIGDEIPQEILEERVRAAFAFPAPVANVESDVGCLELFHGPTLAFKDFGGRFMAQMLTHIAGDKPVTILTATSGDTGAAVAHAFYGLPNVKVVILYPRGKISPLQEKLFCTLGGNIETVAIDGDFDACQALVKQAFDDEELKVALGLNSANSINISRLLAQICYYFEAVAQLPQETRNQLVVSVPSGNFGDLTAGLLAKSLGLPVKRFIAATNVNDTVPRFLHDGQWSPKATQATLSNAMDVSQPNNWPRVEELFRRKIWQLKELGYAAVDDETTQQTMRELKELGYTSEPHAAVAYRALRDQLNPGEYGLFLGTAHPAKFKESVEAILGETLDLPKELAERADLPLLSHNLPADFAALRKLMMNHQ","gaps":0,"evalue":0,"query_to":428,"query_from":1,"hseq":"MKLYNLKDHNEQVSFAQAVTQGLGKNQGLFFPHDLPEFSLTEIDEMLKLDFVTRSAKILSAFIGDEIPQEILEERVRAAFAFPAPVANVESDVGCLELFHGPTLAFKDFGGRFMAQMLTHIAGDKPVTILTATSGDTGAAVAHAFYGLPNVKVVILYPRGKISPLQEKLFCTLGGNIETVAIDGDFDACQALVKQAFDDEELKVALGLNSANSINISRLLAQICYYFEAVAQLPQETRNQLVVSVPSGNFGDLTAGLLAKSLGLPVKRFIAATNVNDTVPRFLHDGQWSPKATQATLSNAMDVSQPNNWPRVEELFRRKIWQLKELGYAAVDDETTQQTMRELKELGYTSEPHAAVAYRALRDQLNPGEYGLFLGTAHPAKFKESVEAILGETLDLPKELAERADLPLLSHNLPADFAALRKLMMNHQ","num":1,"align_len":428}]}],"query_title":"fig|83333.1.peg.4","query_len":428,"query_id":"fig|83333.1.peg.4","stat":{"lambda":0.267,"hsp_len":86,"kappa":0.041,"entropy":0.14,"db_num":4309,"eff_space":335033460,"db_len":1350204}}},"version":"BLASTP 2.3.0+","program":"blastp","reference":"Stephen F. Altschul, Thomas L. Madden, Alejandro A. Schäffer, Jinghui Zhang, Zheng Zhang, Webb Miller, and David J. Lipman (1997), \"Gapped BLAST and PSI-BLAST: a new generation of protein database search programs\", Nucleic Acids Res. 25:3389-3402."}}],{"kb|g.0.peg.4288":{"genome_name":"Escherichia coli K12","function":"Threonine synthase (EC 4.2.3.1)","genome_id":"kb|g.0"}}],"id":"8527913568541408","version":"1.1"}';
        output = {'json_output': queryReturn}
        # jsonQueryReturn = json.loads(queryReturn)

        returnVal = {
            'BlastOutput_db': '',
            'BlastOutput_program': '',
            'BlastOutput_query-ID': '',
            'BlastOutput_query-def': '',
            'BlastOutput_query-len': '',
            'BlastOutput_reference': '',
            'BlastOutput_version': '',
            'BlastOutput_param': {
                'Parameters': {
                    'Parameters_expect': '',
                    'Parameters_filter': '',
                    'Parameters_gap-extend': '',
                    'Parameters_gap-open': '',
                    'Parameters_matrix': '',
                    'Parameters_sc-match': '',
                    'Parameters_sc-mismatch': ''
                }
            },
            'BlastOutput_iterations': {
                'Iteration': [
                    {
                        'Iteration_hits': {
                            'Hit': [
                                {
                                    'Hit_accession': '',
                                    'Hit_def': '',
                                    'Hit_id': '',
                                    'Hit_len': '',
                                    'Hit_num': '',
                                    'Hit_hsps': {
                                        'Hsp': [
                                            {
                                                'Hsp_align-len': '',
                                                'Hsp_bit-score': '',
                                                'Hsp_evalue': '',
                                                'Hsp_hit-frame': '',
                                                'Hsp_hit-from': '',
                                                'Hsp_hit-to': '',
                                                'Hsp_hseq': '',
                                                'Hsp_identity': '',
                                                'Hsp_midline': '',
                                                'Hsp_num': '',
                                                'Hsp_positive': '',
                                                'Hsp_qseq': '',
                                                'Hsp_query-frame': '',
                                                'Hsp_query-from': '',
                                                'Hsp_query-to': '',
                                                'Hsp_score': ''
                                            }
                                        ]
                                    }
                                }
                            ]
                        },
                        'Iteration_iter-num': '',
                        'Iteration_query-ID': '',
                        'Iteration_query-def': '',
                        'Iteration_query-len': ''
                    }
                ]
            }
        }
        print output
        #END blast_fasta

        # At some point might do deeper type checking...
        if not isinstance(output, dict):
            raise ValueError('Method blast_fasta return value ' +
                             'output is not type dict as required.')
        # return the results
        return [output]
<|endoftext|>


<commit_before>from collections import deque

from hwt.hdl.constants import Time
from hwt.simulator.agentBase import AgentBase, SyncAgentBase
from hwt.synthesizer.exceptions import IntfLvlConfErr
from hwt.simulator.hdlSimulator import Timer

# 100 MHz
DEFAULT_CLOCK = 10 * Time.ns

class SignalAgent(SyncAgentBase):
    """
    Agent for signal interface, it can use clock and reset interface
    for synchronization or can be synchronized by delay

    :attention: clock synchronization has higher priority
    """

    def __init__(self, intf, delay=DEFAULT_CLOCK):
        AgentBase.__init__(self, intf)
        self.delay = delay
        self.initDelay = 0

        # resolve clk and rstn
        try:
            self.clk = self.intf._getAssociatedClk()
        except IntfLvlConfErr:
            self.clk = None

        self._discoverReset(True)
        self.data = deque()

        self.initPending = True

        if self.clk is not None:
            if self.initDelay:
                raise NotImplementedError("initDelay only without clock")
            c = self.SELECTED_EDGE_CALLBACK
            self.monitor = c(self.clk, self.monitor, self.getEnable)
            self.driver = c(self.clk, self.driver, self.getEnable)

    def getDrivers(self):
        d = SyncAgentBase.getDrivers(self)
        if self.clk is None:
            return d
        else:
            return d + [self.driverInit_nonClk]

    def driverInit_nonClk(self, sim):
        try:
            d = self.data[0]
        except IndexError:
            d = None

        self.doWrite(sim, d)

        return
        yield

    def doRead(self, s):
        return self.intf.read()

    def doWrite(self, s, data):
        self.intf.write(data)

    def driver(self, sim):
        if self.clk is None:
            if self.initPending:
                if self.initDelay:
                    yield Timer(self.initDelay)
                self.initPending = False
            # if clock is specified this function is periodically called every
            # clk tick
            while True:
                if self._enabled and self.data and self.notReset(sim):
                    d = self.data.popleft()
                    self.doWrite(sim, d)
                yield Timer(self.delay)
        else:
            # if clock is specified this function is periodically called every
            # clk tick, when agent is enabled
            if self.data and self.notReset(sim):
                d = self.data.popleft()
                self.doWrite(sim, d)

    def monitor(self, sim):
        if self.clk is None:
            if self.initPending and self.initDelay:
                yield Timer(self.initDelay)
                self.initPending = False
            # if there is no clk, we have to manage periodic call by our selfs
            while True:
                if self._enabled and self.notReset(sim):
                    yield sim.waitOnCombUpdate()
                    d = self.doRead(sim)
                    self.data.append(d)
                    yield Timer(self.delay)
        else:
            # if clock is specified this function is periodically called every
            # clk tick, when agent is enabled
            yield sim.waitOnCombUpdate()
            if self.notReset(sim):
                d = self.doRead(sim)
                self.data.append(d)
<commit_msg>codestyle<commit_after>from collections import deque

from hwt.hdl.constants import Time
from hwt.simulator.agentBase import AgentBase, SyncAgentBase
from hwt.synthesizer.exceptions import IntfLvlConfErr
from hwt.simulator.hdlSimulator import Timer

# 100 MHz
DEFAULT_CLOCK = 10 * Time.ns

class SignalAgent(SyncAgentBase):
    """
    Agent for signal interface, it can use clock and reset interface
    for synchronization or can be synchronized by delay

    :attention: clock synchronization has higher priority
    """

    def __init__(self, intf, delay=DEFAULT_CLOCK):
        AgentBase.__init__(self, intf)
        self.delay = delay
        self.initDelay = 0

        # resolve clk and rstn
        try:
            self.clk = self.intf._getAssociatedClk()
        except IntfLvlConfErr:
            self.clk = None

        self._discoverReset(True)
        self.data = deque()

        self.initPending = True

        if self.clk is not None:
            if self.initDelay:
                raise NotImplementedError("initDelay only without clock")
            c = self.SELECTED_EDGE_CALLBACK
            self.monitor = c(self.clk, self.monitor, self.getEnable)
            self.driver = c(self.clk, self.driver, self.getEnable)

    def getDrivers(self):
        d = SyncAgentBase.getDrivers(self)
        if self.clk is None:
            return d
        else:
            return d + [self.driverInit_nonClk]

    def driverInit_nonClk(self, sim):
        try:
            d = self.data[0]
        except IndexError:
            d = None

        self.doWrite(sim, d)

        return
        yield

    def doRead(self, s):
        return self.intf.read()

    def doWrite(self, s, data):
        self.intf.write(data)

    def driver(self, sim):
        if self.clk is None:
            if self.initPending:
                if self.initDelay:
                    yield Timer(self.initDelay)
                self.initPending = False
            # if clock is specified this function is periodically called every
            # clk tick
            while True:
                if self._enabled and self.data and self.notReset(sim):
                    d = self.data.popleft()
                    self.doWrite(sim, d)
                yield Timer(self.delay)
        else:
            # if clock is specified this function is periodically called every
            # clk tick, when agent is enabled
            if self.data and self.notReset(sim):
                d = self.data.popleft()
                self.doWrite(sim, d)

    def monitor(self, sim):
        if self.clk is None:
            if self.initPending and self.initDelay:
                yield Timer(self.initDelay)
                self.initPending = False
            # if there is no clk, we have to manage periodic call by our self
            while True:
                if self._enabled and self.notReset(sim):
                    yield sim.waitOnCombUpdate()
                    d = self.doRead(sim)
                    self.data.append(d)
                    yield Timer(self.delay)
        else:
            # if clock is specified this function is periodically called every
            # clk tick, when agent is enabled
            yield sim.waitOnCombUpdate()
            if self.notReset(sim):
                d = self.doRead(sim)
                self.data.append(d)
<|endoftext|>


<commit_before># coding=utf-8
# Copyright 2018 The Hypebot Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Collection of all of the various strings hypebot uses for output.

Please keep sorted by alpabetical order of variable names.
"""

from __future__ import unicode_literals

# pylint: disable=anomalous-backslash-in-string
_DANK_MEMES = [
    'One does not simply win weekend tourneys.',
    'I deserve Challenjour, gg',
    ':^)',
    'ヽ༼ຈل͜ຈ༽ﾉ ヽ༼ຈل͜ຈ༽ﾉ ヽ༼ຈل͜ຈ༽ﾉ ヽ༼ຈل͜ຈ༽ﾉ ヽ༼ຈل͜ຈ༽ﾉ ヽ༼ຈل͜ຈ༽ﾉ ヽ༼ຈل͜ຈ༽ﾉ ヽ༼ຈل͜ຈ༽ﾉ',
    '#worthhype',
    'This channel has more #hype than CLG has potential!',
    '#KABUM2015',
    '#PAIN2016',
    'Better nerf Irelia...',
    'I ate oranges, and it was k.',
    '#TSMTSMTSM',
    '[dankness intensifies]',
    'Not HypeBot; HyyyypeBot.',
    'This is where HypeBot shines!',
    'HypeBot does it all... with style!',
    ('HypeBot\'s mission is to organize the world\'s information and make it '
     'universally dank.'),
    '/me is watching EU LCS.',
    'u wot m8',
    'Misspell disappoint in a bug? Son, I am disappoint.',
    'ayyyyyyyyyyyy lmao',
    'rito pls',
    'D is for Dank.',
    'Interior crocodile alligator, I drive a Chevrolet movie theater.',
    'Same.',
    'Le Toucan has arrived.',
    'Quote me on this, EU is garbage',
    'NA > EU',
    'RIP Clairvoyance Ashe',
    '[chiming intensifies]',
    'Yo, {person}, body these fools!',
    '/me remains unconvinced.',
    'Why do NA supports only play Soraka/Janna/Karma?! ¯\_(ツ)_/¯',
    'Hypbot IV: A Nw Mm',
    '{person} is one of the generally "good guy owners" of HypeBot.',
    ('We do not mind at all if there is a massive delta between Hypebot and '
     'other bots...'),
    'Love me some {person}',
    '/me goes full nuts.',
    'MikeYeung HYPE!',
    ('I\'m not allowed to disclose the numbers but trust me, it wasn\'t a '
     'close race.'),
    '👹 You look familiar.',
]
_TEAM_MEMES = [
    '#{team}Hype!',
    'Brace yourself, Team {team} is coming.',
    'I don\'t always host a tournament, but when I do Team {team} wins!',
]
_MEME_TEAMS = [
    'HypeBot',
]
# Ensure that the team memes don't overshadow the dank memes.
_DANK_WEIGHT = (len(_TEAM_MEMES) * len(_MEME_TEAMS)) // len(_DANK_MEMES) + 1
ALL_MEMES = _DANK_MEMES * _DANK_WEIGHT + [
    meme.format(team=team) for team in _MEME_TEAMS for meme in _TEAM_MEMES]
FALLBACK_LIVESTREAM_LINK = 'Check https://gaming.youtube.com for the link'
FREELO = [
    ('Did you know there are other ways to win besides stomping your lane '
     'opponent? Try typing "?" in all chat any time someone on the enemy team '
     'dies.'),
    ('Any time your jungler is in another lane, make sure you let him know '
     'your true feelings about it!'),
    ('Communication with your teammates is important! Be sure to inform your '
     'entire team whenever a teammate is feeding their lane opponent, or '
     'failed a flash or whiffed a skillshot!'),
    ('Always buy a control ward when you go back to base! That way you can '
     'sell it later if you are 30g short!'),
    'Miss Fortune\'s first name is Sarah and Vayne\'s is Shauna',
    'If at first you don\'t succeed, try flaming again.',
    ('If Wukong stops moving when being chased, it means he accepts his fate '
     'so you should ult him.'),
    'If nocturne ults, just turn up your brightness. It\'s not a big deal.',
    'It\'s only the jungler\'s fault when you are not the jungler.',
    ('If the opposing laner gets ahead of you, make sure your jungler knows '
     'it\'s his fault so he can correct it in future games!'),
    ('Chasing after Singed is a great way to make your Spectre\'s Cowl as '
     'gold efficient as possible!'),
    ('When playing Mordekaiser, be sure to feed the enemy marksmen early to '
     'increase the strength of your puppet.'),
    ('When playing Blitzcrank, prioritize hooking the enemy Amumu so your team '
     'can burst him down before he can ult.'),
    'Remember to spam AOE abilities under the tower to help your ADC last hit.',
    ('You can catch enemy Draven\'s axes! Make sure to flash forward to steal '
     'his to conserve mana.'),
    ('The more an item costs, the better it is. This makes trinkets the worst '
     'items in the game, don\'t waste time trying to use them.'),
    ('Gnar has great AP ratios! Make sure you go for an early deathcap '
     'to make his GNAR! and Hyper do some serious damage.'),
    ('If you have trouble keeping up with your opponent\'s leveling, try buying'
     ' an EXP boost!'),
    ('Don\'t worry about building magic resist against Ryze because he does '
     'mana damage.'),
    ('When playing Cho\'Gath, try not to get too many stacks, as it makes it '
     'easier for the enemy to hit you.'),
    ('Your enemy will know you\'re the jungler if you take smite. Take ignite '
     'or teleport instead to play mind games.'),
    ('When teamfighting, always focus the enemy marksmen or mages. You should '
     'never focus the enemy tank.'),
    'Laugh is the most powerful skill in the game.',
    ('After acing the enemy team at their base, you should go back and take '
     'their jungle instead of the inhibitor. Inhibitors only give 50g which is '
     'less efficient.'),
    'When playing Bard, be sure to ult your wards to extend their timers.',
    ('Runaan\'s Hurricane lets Vayne deal true damage to three champions at '
     'once.'),
    ('If you\'re falling behind in farm, let the enemy kill your inhibitor. '
     'Super minions grant you more gold and deny your lane opponent cs.'),
    ('Use Ghost/Flash to get back to lane when playing against Zoe, ensuring '
     'they cannot be used against you.'),
]
HYPEBOT_IS_THE_CHAMP_STRING = ('HypeBot is a L7-9 Vision main, generating ∞ '
                               'chests this season.')
HYPEBOT_IS_THE_CHIMP_STRING = 'HypeBot doesn\'t monkey around.'
HYPEBOT_ALL_CHAMPS_STRING = 'HypeBot knows champs, HypeBot has the best champs.'
POEM = [
    'There was once a hype bot with dank memes who was very lonely.',
    'why was it lonely?',
    'All things must !raise this bot, so they shunned it.',
    'did it chase them all?',
    'It took an axe and rekt itself in two, right down the middle.',
    'hypebot, wtf',
    'So it would always have a #Hype.',
]
ROOSTERS = [
    'cock-a-doodle-doo',
    'koekelekoe',
    'kikiriki',
    'gokogoko',
    'cocorico',
    'cuc-a-dudal-du',
    'quiquiriquí',
    'קוקוריקו',
    'chichirichí',
    'Foghorn Leghorn',
    'Albert Eggstein',
    'gallo',
    'coq',
    'Hahn Solo',
    '公鸡',
    '雄鶏',
]
SCHEDULE_NO_GAMES_STRING = ('Tune in next season to see if NA makes it out of '
                            'groups.')
WHO_IS_HYPEBOT_STRING = ('HypeBot = ¯\_(ツ)_/¯ [DECAKILL, Challenjour (KR), '
                         'Ranked LCK 1v9: Teemo, 1337pts (W)]')
<commit_msg>Update the fallback livestream link to point to the new home for Gaming on YouTube.<commit_after># coding=utf-8
# Copyright 2018 The Hypebot Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Collection of all of the various strings hypebot uses for output.

Please keep sorted by alpabetical order of variable names.
"""

from __future__ import unicode_literals

# pylint: disable=anomalous-backslash-in-string
_DANK_MEMES = [
    'One does not simply win weekend tourneys.',
    'I deserve Challenjour, gg',
    ':^)',
    'ヽ༼ຈل͜ຈ༽ﾉ ヽ༼ຈل͜ຈ༽ﾉ ヽ༼ຈل͜ຈ༽ﾉ ヽ༼ຈل͜ຈ༽ﾉ ヽ༼ຈل͜ຈ༽ﾉ ヽ༼ຈل͜ຈ༽ﾉ ヽ༼ຈل͜ຈ༽ﾉ ヽ༼ຈل͜ຈ༽ﾉ',
    '#worthhype',
    'This channel has more #hype than CLG has potential!',
    '#KABUM2015',
    '#PAIN2016',
    'Better nerf Irelia...',
    'I ate oranges, and it was k.',
    '#TSMTSMTSM',
    '[dankness intensifies]',
    'Not HypeBot; HyyyypeBot.',
    'This is where HypeBot shines!',
    'HypeBot does it all... with style!',
    ('HypeBot\'s mission is to organize the world\'s information and make it '
     'universally dank.'),
    '/me is watching EU LCS.',
    'u wot m8',
    'Misspell disappoint in a bug? Son, I am disappoint.',
    'ayyyyyyyyyyyy lmao',
    'rito pls',
    'D is for Dank.',
    'Interior crocodile alligator, I drive a Chevrolet movie theater.',
    'Same.',
    'Le Toucan has arrived.',
    'Quote me on this, EU is garbage',
    'NA > EU',
    'RIP Clairvoyance Ashe',
    '[chiming intensifies]',
    'Yo, {person}, body these fools!',
    '/me remains unconvinced.',
    'Why do NA supports only play Soraka/Janna/Karma?! ¯\_(ツ)_/¯',
    'Hypbot IV: A Nw Mm',
    '{person} is one of the generally "good guy owners" of HypeBot.',
    ('We do not mind at all if there is a massive delta between Hypebot and '
     'other bots...'),
    'Love me some {person}',
    '/me goes full nuts.',
    'MikeYeung HYPE!',
    ('I\'m not allowed to disclose the numbers but trust me, it wasn\'t a '
     'close race.'),
    '👹 You look familiar.',
]
_TEAM_MEMES = [
    '#{team}Hype!',
    'Brace yourself, Team {team} is coming.',
    'I don\'t always host a tournament, but when I do Team {team} wins!',
]
_MEME_TEAMS = [
    'HypeBot',
]
# Ensure that the team memes don't overshadow the dank memes.
_DANK_WEIGHT = (len(_TEAM_MEMES) * len(_MEME_TEAMS)) // len(_DANK_MEMES) + 1
ALL_MEMES = _DANK_MEMES * _DANK_WEIGHT + [
    meme.format(team=team) for team in _MEME_TEAMS for meme in _TEAM_MEMES]
FALLBACK_LIVESTREAM_LINK = 'Check https://www.youtube.com/gaming for the link'
FREELO = [
    ('Did you know there are other ways to win besides stomping your lane '
     'opponent? Try typing "?" in all chat any time someone on the enemy team '
     'dies.'),
    ('Any time your jungler is in another lane, make sure you let him know '
     'your true feelings about it!'),
    ('Communication with your teammates is important! Be sure to inform your '
     'entire team whenever a teammate is feeding their lane opponent, or '
     'failed a flash or whiffed a skillshot!'),
    ('Always buy a control ward when you go back to base! That way you can '
     'sell it later if you are 30g short!'),
    'Miss Fortune\'s first name is Sarah and Vayne\'s is Shauna',
    'If at first you don\'t succeed, try flaming again.',
    ('If Wukong stops moving when being chased, it means he accepts his fate '
     'so you should ult him.'),
    'If nocturne ults, just turn up your brightness. It\'s not a big deal.',
    'It\'s only the jungler\'s fault when you are not the jungler.',
    ('If the opposing laner gets ahead of you, make sure your jungler knows '
     'it\'s his fault so he can correct it in future games!'),
    ('Chasing after Singed is a great way to make your Spectre\'s Cowl as '
     'gold efficient as possible!'),
    ('When playing Mordekaiser, be sure to feed the enemy marksmen early to '
     'increase the strength of your puppet.'),
    ('When playing Blitzcrank, prioritize hooking the enemy Amumu so your team '
     'can burst him down before he can ult.'),
    'Remember to spam AOE abilities under the tower to help your ADC last hit.',
    ('You can catch enemy Draven\'s axes! Make sure to flash forward to steal '
     'his to conserve mana.'),
    ('The more an item costs, the better it is. This makes trinkets the worst '
     'items in the game, don\'t waste time trying to use them.'),
    ('Gnar has great AP ratios! Make sure you go for an early deathcap '
     'to make his GNAR! and Hyper do some serious damage.'),
    ('If you have trouble keeping up with your opponent\'s leveling, try buying'
     ' an EXP boost!'),
    ('Don\'t worry about building magic resist against Ryze because he does '
     'mana damage.'),
    ('When playing Cho\'Gath, try not to get too many stacks, as it makes it '
     'easier for the enemy to hit you.'),
    ('Your enemy will know you\'re the jungler if you take smite. Take ignite '
     'or teleport instead to play mind games.'),
    ('When teamfighting, always focus the enemy marksmen or mages. You should '
     'never focus the enemy tank.'),
    'Laugh is the most powerful skill in the game.',
    ('After acing the enemy team at their base, you should go back and take '
     'their jungle instead of the inhibitor. Inhibitors only give 50g which is '
     'less efficient.'),
    'When playing Bard, be sure to ult your wards to extend their timers.',
    ('Runaan\'s Hurricane lets Vayne deal true damage to three champions at '
     'once.'),
    ('If you\'re falling behind in farm, let the enemy kill your inhibitor. '
     'Super minions grant you more gold and deny your lane opponent cs.'),
    ('Use Ghost/Flash to get back to lane when playing against Zoe, ensuring '
     'they cannot be used against you.'),
]
HYPEBOT_IS_THE_CHAMP_STRING = ('HypeBot is a L7-9 Vision main, generating ∞ '
                               'chests this season.')
HYPEBOT_IS_THE_CHIMP_STRING = 'HypeBot doesn\'t monkey around.'
HYPEBOT_ALL_CHAMPS_STRING = 'HypeBot knows champs, HypeBot has the best champs.'
POEM = [
    'There was once a hype bot with dank memes who was very lonely.',
    'why was it lonely?',
    'All things must !raise this bot, so they shunned it.',
    'did it chase them all?',
    'It took an axe and rekt itself in two, right down the middle.',
    'hypebot, wtf',
    'So it would always have a #Hype.',
]
ROOSTERS = [
    'cock-a-doodle-doo',
    'koekelekoe',
    'kikiriki',
    'gokogoko',
    'cocorico',
    'cuc-a-dudal-du',
    'quiquiriquí',
    'קוקוריקו',
    'chichirichí',
    'Foghorn Leghorn',
    'Albert Eggstein',
    'gallo',
    'coq',
    'Hahn Solo',
    '公鸡',
    '雄鶏',
]
SCHEDULE_NO_GAMES_STRING = ('Tune in next season to see if NA makes it out of '
                            'groups.')
WHO_IS_HYPEBOT_STRING = ('HypeBot = ¯\_(ツ)_/¯ [DECAKILL, Challenjour (KR), '
                         'Ranked LCK 1v9: Teemo, 1337pts (W)]')
<|endoftext|>


<commit_before>"""A module containing tests for the library representation of Schemas."""
from lxml import etree
import pytest
import iati.core.codelists
import iati.core.default
import iati.core.exceptions
import iati.core.schemas
import iati.core.tests.utilities
from iati.core.tests.utilities import standard_version_optional

class TestSchemas(object):
    """A container for tests relating to Schemas."""

    @pytest.fixture(params=[
        iati.core.default.activity_schema,
        iati.core.default.organisation_schema
    ])
    def schema_initialised(self, request, standard_version_optional):
        """Create and return a single ActivitySchema or OrganisaionSchema object.
        For use where both ActivitySchema and OrganisaionSchema must produce the same result.

        Returns:
            iati.core.ActivitySchema / iati.core.OrganisationSchema: An activity and organisaion that has been initialised based on the default IATI Activity and Organisaion schemas.

        """
        schema_func = request.param

        return schema_func(*standard_version_optional)

    @pytest.mark.parametrize("schema_func, expected_root_element_name", [
        (iati.core.default.activity_schema, 'iati-activities'),
        (iati.core.default.organisation_schema, 'iati-organisations')
    ])
    def test_schema_default_attributes(self, standard_version_optional, schema_func, expected_root_element_name):
        """Check a Schema's default attributes are correct."""
        schema = schema_func(*standard_version_optional)

        assert schema.ROOT_ELEMENT_NAME == expected_root_element_name
        assert expected_root_element_name in schema._source_path

    def test_schema_define_from_xsd(self, schema_initialised):
        """Check that a Schema can be generated from an XSD definition."""
        assert isinstance(schema_initialised.codelists, set)
        assert not schema_initialised.codelists
        assert isinstance(schema_initialised.rulesets, set)
        assert not schema_initialised.rulesets

    @pytest.mark.parametrize("schema_func", [
        iati.core.default.activity_schema,
        iati.core.default.organisation_schema
    ])
    @pytest.mark.parametrize('version', ['1.04']) # iati.core.constants.STANDARD_VERSIONS)
    def test_schema_get_version(self, schema_func, version):
        """Check that the correct version number is returned by the base classes of iati.core.schemas.schema._get_version()."""
        schema = schema_func(version)
        result = schema._get_version()

        assert result == version

    def test_schema_unmodified_includes(self, schema_initialised):
        """Check that local elements can be accessed, but imported elements within unmodified Schema includes cannot be accessed.

        lxml does not contain functionality to access elements within imports defined along the lines of:
        `<xsd:include schemaLocation="NAME.xsd" />`

        Todo:
            Simplify asserts.

            Consider consolidating variables shared between multiple tests.

        """
        schema = schema_initialised
        local_element = schema.ROOT_ELEMENT_NAME
        included_element = 'reporting-org'

        include_location_xpath = (iati.core.constants.NAMESPACE + 'include')
        local_xpath = (iati.core.constants.NAMESPACE + 'element[@name="' + local_element + '"]')
        included_xpath = (iati.core.constants.NAMESPACE + 'element[@name="' + included_element + '"]')

        assert schema._schema_base_tree.getroot().find(include_location_xpath).attrib['schemaLocation'] == 'iati-common.xsd'
        assert isinstance(schema._schema_base_tree.getroot().find(local_xpath), etree._Element)
        assert schema._schema_base_tree.getroot().find(included_xpath) is None

    def test_schema_modified_includes(self, schema_initialised):
        """Check that elements within unflattened modified Schema includes cannot be accessed.

        lxml contains functionality to access elements within imports defined along the lines of:
        `<xi:include href="NAME.xsd" parse="xml" />`
        when there is a namespace defined against the root schema element as `xmlns:xi="http://www.w3.org/2001/XInclude"`

        Todo:
            Simplify asserts.

            Consider consolidating variables shared between multiple tests.

        """
        schema = schema_initialised
        local_element = schema.ROOT_ELEMENT_NAME
        included_element = 'reporting-org'

        include_location_xpath = (iati.core.constants.NAMESPACE + 'include')
        xi_location_xpath = ('{http://www.w3.org/2001/XInclude}include')
        local_xpath = (iati.core.constants.NAMESPACE + 'element[@name="' + local_element + '"]')
        included_xpath = (iati.core.constants.NAMESPACE + 'element[@name="' + included_element + '"]')

        include_location = schema._schema_base_tree.getroot().find(include_location_xpath).attrib['schemaLocation']
        tree = schema._change_include_to_xinclude(schema._schema_base_tree)
        xi_node = tree.getroot().find(xi_location_xpath)
        include_node_after = tree.getroot().find(include_location_xpath)

        # check that the new element has been added
        assert isinstance(xi_node, etree._Element)
        assert xi_node.attrib['href'][-len(include_location):] == include_location
        assert xi_node.attrib['parse'] == 'xml'
        assert isinstance(tree.getroot().find(local_xpath), etree._Element)
        assert not isinstance(tree.getroot().find(included_xpath), etree._Element)
        # check that the old element has been removed
        assert include_node_after is None

    def test_schema_flattened_includes(self, schema_initialised):
        """Check that includes are flattened correctly.

        In a full flatten of included elements as `<xi:include href="NAME.xsd" parse="xml" />`, there may be nested `schema` elements and other situations that are not permitted.

        This checks that the flattened xsd is valid and that included elements can be accessed.

        Todo:
            Simplify asserts.

            Consider consolidating variables shared between multiple tests.

            Assert that the flattened XML is a valid Schema.

        """
        schema = schema_initialised
        local_element = schema.ROOT_ELEMENT_NAME
        included_element = 'reporting-org'

        include_location_xpath = (iati.core.constants.NAMESPACE + 'include')
        xi_location_xpath = ('{http://www.w3.org/2001/XInclude}include')
        local_xpath = (iati.core.constants.NAMESPACE + 'element[@name="' + local_element + '"]')
        included_xpath = (iati.core.constants.NAMESPACE + 'element[@name="' + included_element + '"]')

        tree = schema.flatten_includes(schema._schema_base_tree)

        assert tree.getroot().find(include_location_xpath) is None
        assert tree.getroot().find(xi_location_xpath) is None
        assert isinstance(tree.getroot().find(local_xpath), etree._Element)
        assert isinstance(tree.getroot().find(included_xpath), etree._Element)
        assert iati.core.utilities.convert_tree_to_schema(tree)

    def test_schema_codelists_add(self, schema_initialised):
        """Check that it is possible to add Codelists to the Schema."""
        codelist_name = "a test Codelist name"
        codelist = iati.core.Codelist(codelist_name)

        schema_initialised.codelists.add(codelist)

        assert len(schema_initialised.codelists) == 1

    def test_schema_codelists_add_twice(self, schema_initialised):
        """Check that it is not possible to add the same Codelist to a Schema multiple times.

        Todo:
            Consider if this test should test against a versioned Codelist.
        """
        codelist_name = "a test Codelist name"
        codelist = iati.core.Codelist(codelist_name)

        schema_initialised.codelists.add(codelist)
        schema_initialised.codelists.add(codelist)

        assert len(schema_initialised.codelists) == 1

    def test_schema_codelists_add_duplicate(self, schema_initialised):
        """Check that it is not possible to add multiple functionally identical Codelists to a Schema.

        Todo:
            Consider if this test should test against a versioned Codelist.
        """
        codelist_name = "a test Codelist name"
        codelist = iati.core.Codelist(codelist_name)
        codelist2 = iati.core.Codelist(codelist_name)

        schema_initialised.codelists.add(codelist)
        schema_initialised.codelists.add(codelist2)

        assert len(schema_initialised.codelists) == 1

    def test_schema_rulesets_add(self, schema_initialised):
        """Check that it is possible to add Rulesets to the Schema.

        Todo:
            Consider if this test should test against a versioned Ruleset.
        """
        ruleset = iati.core.Ruleset()

        schema_initialised.rulesets.add(ruleset)

        assert len(schema_initialised.rulesets) == 1

    @pytest.mark.skip(reason='Not implemented')
    def test_schema_rulesets_add_twice(self, schema_initialised):
        """Check that it is not possible to add the sameRulesets to a Schema multiple times.

        Todo:
            Consider if this test should test against a versioned Ruleset.
        """
        raise NotImplementedError

    @pytest.mark.skip(reason='Not implemented')
    def test_schema_rulesets_add_duplicate(self, schema_initialised):
        """Check that it is not possible to add multiple functionally identical Rulesets to a Schema.

        Todo:
            Consider if this test should test against a versioned Ruleset.
        """
        raise NotImplementedError
<commit_msg>Directly create Schemas rather than using defaults<commit_after>"""A module containing tests for the library representation of Schemas."""
from collections import namedtuple
from lxml import etree
import pytest
import iati.core.codelists
import iati.core.default
import iati.core.exceptions
import iati.core.resources
import iati.core.schemas
import iati.core.tests.utilities
from iati.core.tests.utilities import standard_version_optional

class TestSchemas(object):
    """A container for tests relating to Schemas."""

    @pytest.fixture(params=[
        {
            "path_func": iati.core.resources.get_all_activity_schema_paths,
            "schema_class": iati.core.ActivitySchema
        },
        {
            "path_func": iati.core.resources.get_all_org_schema_paths,
            "schema_class": iati.core.OrganisationSchema
        }
    ])
    def schema_initialised(self, request, standard_version_optional):
        """Create and return a single ActivitySchema or OrganisaionSchema object.
        For use where both ActivitySchema and OrganisaionSchema must produce the same result.

        Returns:
            iati.core.ActivitySchema / iati.core.OrganisationSchema: An activity and organisaion that has been initialised based on the default IATI Activity and Organisaion schemas.

        """
        schema_path = request.param['path_func'](*standard_version_optional)[0]
        return request.param['schema_class'](schema_path)

    @pytest.mark.parametrize("schema_func, expected_root_element_name", [
        (iati.core.default.activity_schema, 'iati-activities'),
        (iati.core.default.organisation_schema, 'iati-organisations')
    ])
    def test_schema_default_attributes(self, standard_version_optional, schema_func, expected_root_element_name):
        """Check a Schema's default attributes are correct."""
        schema = schema_func(*standard_version_optional)

        assert schema.ROOT_ELEMENT_NAME == expected_root_element_name
        assert expected_root_element_name in schema._source_path

    def test_schema_define_from_xsd(self, schema_initialised):
        """Check that a Schema can be generated from an XSD definition."""
        assert isinstance(schema_initialised.codelists, set)
        assert not schema_initialised.codelists
        assert isinstance(schema_initialised.rulesets, set)
        assert not schema_initialised.rulesets

    @pytest.mark.parametrize("schema_func", [
        iati.core.default.activity_schema,
        iati.core.default.organisation_schema
    ])
    @pytest.mark.parametrize('version', ['1.04']) # iati.core.constants.STANDARD_VERSIONS)
    def test_schema_get_version(self, schema_func, version):
        """Check that the correct version number is returned by the base classes of iati.core.schemas.schema._get_version()."""
        schema = schema_func(version)
        result = schema._get_version()

        assert result == version

    def test_schema_unmodified_includes(self, schema_initialised):
        """Check that local elements can be accessed, but imported elements within unmodified Schema includes cannot be accessed.

        lxml does not contain functionality to access elements within imports defined along the lines of:
        `<xsd:include schemaLocation="NAME.xsd" />`

        Todo:
            Simplify asserts.

            Consider consolidating variables shared between multiple tests.

        """
        schema = schema_initialised
        local_element = schema.ROOT_ELEMENT_NAME
        included_element = 'reporting-org'

        include_location_xpath = (iati.core.constants.NAMESPACE + 'include')
        local_xpath = (iati.core.constants.NAMESPACE + 'element[@name="' + local_element + '"]')
        included_xpath = (iati.core.constants.NAMESPACE + 'element[@name="' + included_element + '"]')

        assert schema._schema_base_tree.getroot().find(include_location_xpath).attrib['schemaLocation'] == 'iati-common.xsd'
        assert isinstance(schema._schema_base_tree.getroot().find(local_xpath), etree._Element)
        assert schema._schema_base_tree.getroot().find(included_xpath) is None

    def test_schema_modified_includes(self, schema_initialised):
        """Check that elements within unflattened modified Schema includes cannot be accessed.

        lxml contains functionality to access elements within imports defined along the lines of:
        `<xi:include href="NAME.xsd" parse="xml" />`
        when there is a namespace defined against the root schema element as `xmlns:xi="http://www.w3.org/2001/XInclude"`

        Todo:
            Simplify asserts.

            Consider consolidating variables shared between multiple tests.

        """
        schema = schema_initialised
        local_element = schema.ROOT_ELEMENT_NAME
        included_element = 'reporting-org'

        include_location_xpath = (iati.core.constants.NAMESPACE + 'include')
        xi_location_xpath = ('{http://www.w3.org/2001/XInclude}include')
        local_xpath = (iati.core.constants.NAMESPACE + 'element[@name="' + local_element + '"]')
        included_xpath = (iati.core.constants.NAMESPACE + 'element[@name="' + included_element + '"]')

        include_location = schema._schema_base_tree.getroot().find(include_location_xpath).attrib['schemaLocation']
        tree = schema._change_include_to_xinclude(schema._schema_base_tree)
        xi_node = tree.getroot().find(xi_location_xpath)
        include_node_after = tree.getroot().find(include_location_xpath)

        # check that the new element has been added
        assert isinstance(xi_node, etree._Element)
        assert xi_node.attrib['href'][-len(include_location):] == include_location
        assert xi_node.attrib['parse'] == 'xml'
        assert isinstance(tree.getroot().find(local_xpath), etree._Element)
        assert not isinstance(tree.getroot().find(included_xpath), etree._Element)
        # check that the old element has been removed
        assert include_node_after is None

    def test_schema_flattened_includes(self, schema_initialised):
        """Check that includes are flattened correctly.

        In a full flatten of included elements as `<xi:include href="NAME.xsd" parse="xml" />`, there may be nested `schema` elements and other situations that are not permitted.

        This checks that the flattened xsd is valid and that included elements can be accessed.

        Todo:
            Simplify asserts.

            Consider consolidating variables shared between multiple tests.

            Assert that the flattened XML is a valid Schema.

        """
        schema = schema_initialised
        local_element = schema.ROOT_ELEMENT_NAME
        included_element = 'reporting-org'

        include_location_xpath = (iati.core.constants.NAMESPACE + 'include')
        xi_location_xpath = ('{http://www.w3.org/2001/XInclude}include')
        local_xpath = (iati.core.constants.NAMESPACE + 'element[@name="' + local_element + '"]')
        included_xpath = (iati.core.constants.NAMESPACE + 'element[@name="' + included_element + '"]')

        tree = schema.flatten_includes(schema._schema_base_tree)

        assert tree.getroot().find(include_location_xpath) is None
        assert tree.getroot().find(xi_location_xpath) is None
        assert isinstance(tree.getroot().find(local_xpath), etree._Element)
        assert isinstance(tree.getroot().find(included_xpath), etree._Element)
        assert iati.core.utilities.convert_tree_to_schema(tree)

    def test_schema_codelists_add(self, schema_initialised):
        """Check that it is possible to add Codelists to the Schema."""
        codelist_name = "a test Codelist name"
        codelist = iati.core.Codelist(codelist_name)

        schema_initialised.codelists.add(codelist)

        assert len(schema_initialised.codelists) == 1

    def test_schema_codelists_add_twice(self, schema_initialised):
        """Check that it is not possible to add the same Codelist to a Schema multiple times.

        Todo:
            Consider if this test should test against a versioned Codelist.
        """
        codelist_name = "a test Codelist name"
        codelist = iati.core.Codelist(codelist_name)

        schema_initialised.codelists.add(codelist)
        schema_initialised.codelists.add(codelist)

        assert len(schema_initialised.codelists) == 1

    def test_schema_codelists_add_duplicate(self, schema_initialised):
        """Check that it is not possible to add multiple functionally identical Codelists to a Schema.

        Todo:
            Consider if this test should test against a versioned Codelist.
        """
        codelist_name = "a test Codelist name"
        codelist = iati.core.Codelist(codelist_name)
        codelist2 = iati.core.Codelist(codelist_name)

        schema_initialised.codelists.add(codelist)
        schema_initialised.codelists.add(codelist2)

        assert len(schema_initialised.codelists) == 1

    def test_schema_rulesets_add(self, schema_initialised):
        """Check that it is possible to add Rulesets to the Schema.

        Todo:
            Consider if this test should test against a versioned Ruleset.
        """
        ruleset = iati.core.Ruleset()

        schema_initialised.rulesets.add(ruleset)

        assert len(schema_initialised.rulesets) == 1

    @pytest.mark.skip(reason='Not implemented')
    def test_schema_rulesets_add_twice(self, schema_initialised):
        """Check that it is not possible to add the sameRulesets to a Schema multiple times.

        Todo:
            Consider if this test should test against a versioned Ruleset.
        """
        raise NotImplementedError

    @pytest.mark.skip(reason='Not implemented')
    def test_schema_rulesets_add_duplicate(self, schema_initialised):
        """Check that it is not possible to add multiple functionally identical Rulesets to a Schema.

        Todo:
            Consider if this test should test against a versioned Ruleset.
        """
        raise NotImplementedError
<|endoftext|>


<commit_before>#!/usr/bin/env python

"""
Test for scratchnet.py
"""

import unittest
from mininet.util import pexpect

class testScratchNet( unittest.TestCase ):

    opts = [ "1 packets transmitted, 1 received, 0% packet loss", pexpect.EOF ]

    def pingTest( self, name ):
        "Verify that no ping packets were dropped"
        p = pexpect.spawn( 'python -m %s' % name )
        index = p.expect( self.opts, timeout=120 )
        self.assertEqual( index, 0 )

    def testPingKernel( self ):
        self.pingTest( 'mininet.examples.scratchnet' )

    def testPingUser( self ):
        self.pingTest( 'mininet.examples.scratchnetuser' )

if __name__ == '__main__':
    unittest.main()
<commit_msg>Wait for exit to avoid leftover dp0 (#1002)<commit_after>#!/usr/bin/env python

"""
Test for scratchnet.py
"""

import unittest
from mininet.util import pexpect

class testScratchNet( unittest.TestCase ):

    opts = [ "1 packets transmitted, 1 received, 0% packet loss", pexpect.EOF ]

    def pingTest( self, name ):
        "Verify that no ping packets were dropped"
        p = pexpect.spawn( 'python -m %s' % name )
        index = p.expect( self.opts, timeout=120 )
        self.assertEqual( index, 0 )
        p.wait()

    def testPingKernel( self ):
        self.pingTest( 'mininet.examples.scratchnet' )

    def testPingUser( self ):
        self.pingTest( 'mininet.examples.scratchnetuser' )

if __name__ == '__main__':
    unittest.main()
<|endoftext|>


<commit_before>#!/usr/bin/python
#
# tcpv4connect	Trace TCP IPv4 connect()s.
#		For Linux, uses BCC, eBPF. Embedded C.
#
# USAGE: tcpv4connect [-h] [-t] [-p PID]
#
# This is provided as a basic example of TCP connection & socket tracing.
#
# All IPv4 connection attempts are traced, even if they ultimately fail.
#
# Copyright (c) 2015 Brendan Gregg.
# Licensed under the Apache License, Version 2.0 (the "License")
#
# 15-Oct-2015	Brendan Gregg	Created this.

from __future__ import print_function
from bcc import BPF

# define BPF program
bpf_text = """
#include <uapi/linux/ptrace.h>
#include <net/sock.h>
#include <bcc/proto.h>

BPF_HASH(currsock, u32, struct sock *);

int kprobe__tcp_v4_connect(struct pt_regs *ctx, struct sock *sk)
{
	u32 pid = bpf_get_current_pid_tgid();

	// stash the sock ptr for lookup on return
	currsock.update(&pid, &sk);

	return 0;
};

int kretprobe__tcp_v4_connect(struct pt_regs *ctx)
{
	int ret = PT_REGS_RC(ctx);
	u32 pid = bpf_get_current_pid_tgid();

	struct sock **skpp;
	skpp = currsock.lookup(&pid);
	if (skpp == 0) {
		return 0;	// missed entry
	}

	if (ret != 0) {
		// failed to send SYNC packet, may not have populated
		// socket __sk_common.{skc_rcv_saddr, ...}
		currsock.delete(&pid);
		return 0;
	}

	// pull in details
	struct sock *skp = *skpp;
	u32 saddr = 0, daddr = 0;
	u16 dport = 0;
	bpf_probe_read(&saddr, sizeof(saddr), &skp->__sk_common.skc_rcv_saddr);
	bpf_probe_read(&daddr, sizeof(daddr), &skp->__sk_common.skc_daddr);
	bpf_probe_read(&dport, sizeof(dport), &skp->__sk_common.skc_dport);

	// output
	bpf_trace_printk("trace_tcp4connect %x %x %d\\n", saddr, daddr, ntohs(dport));

	currsock.delete(&pid);

	return 0;
}
"""

# initialize BPF
b = BPF(text=bpf_text)

# header
print("%-6s %-12s %-16s %-16s %-4s" % ("PID", "COMM", "SADDR", "DADDR",
    "DPORT"))

def inet_ntoa(addr):
	dq = ''
	for i in range(0, 4):
		dq = dq + str(addr & 0xff)
		if (i != 3):
			dq = dq + '.'
		addr = addr >> 8
	return dq

# filter and format output
while 1:
        # Read messages from kernel pipe
        try:
            (task, pid, cpu, flags, ts, msg) = b.trace_fields()
            (_tag, saddr_hs, daddr_hs, dport_s) = msg.split(" ")
        except ValueError:
            # Ignore messages from other tracers
            continue

        # Ignore messages from other tracers
        if _tag != "trace_tcp4connect":
            continue

	print("%-6d %-12.12s %-16s %-16s %-4s" % (pid, task,
	    inet_ntoa(int(saddr_hs, 16)),
	    inet_ntoa(int(daddr_hs, 16)),
	    dport_s))
<commit_msg>examples: fix indentation in tracing/tcpv4connect<commit_after>#!/usr/bin/python
#
# tcpv4connect	Trace TCP IPv4 connect()s.
#		For Linux, uses BCC, eBPF. Embedded C.
#
# USAGE: tcpv4connect [-h] [-t] [-p PID]
#
# This is provided as a basic example of TCP connection & socket tracing.
#
# All IPv4 connection attempts are traced, even if they ultimately fail.
#
# Copyright (c) 2015 Brendan Gregg.
# Licensed under the Apache License, Version 2.0 (the "License")
#
# 15-Oct-2015	Brendan Gregg	Created this.

from __future__ import print_function
from bcc import BPF

# define BPF program
bpf_text = """
#include <uapi/linux/ptrace.h>
#include <net/sock.h>
#include <bcc/proto.h>

BPF_HASH(currsock, u32, struct sock *);

int kprobe__tcp_v4_connect(struct pt_regs *ctx, struct sock *sk)
{
	u32 pid = bpf_get_current_pid_tgid();

	// stash the sock ptr for lookup on return
	currsock.update(&pid, &sk);

	return 0;
};

int kretprobe__tcp_v4_connect(struct pt_regs *ctx)
{
	int ret = PT_REGS_RC(ctx);
	u32 pid = bpf_get_current_pid_tgid();

	struct sock **skpp;
	skpp = currsock.lookup(&pid);
	if (skpp == 0) {
		return 0;	// missed entry
	}

	if (ret != 0) {
		// failed to send SYNC packet, may not have populated
		// socket __sk_common.{skc_rcv_saddr, ...}
		currsock.delete(&pid);
		return 0;
	}

	// pull in details
	struct sock *skp = *skpp;
	u32 saddr = 0, daddr = 0;
	u16 dport = 0;
	bpf_probe_read(&saddr, sizeof(saddr), &skp->__sk_common.skc_rcv_saddr);
	bpf_probe_read(&daddr, sizeof(daddr), &skp->__sk_common.skc_daddr);
	bpf_probe_read(&dport, sizeof(dport), &skp->__sk_common.skc_dport);

	// output
	bpf_trace_printk("trace_tcp4connect %x %x %d\\n", saddr, daddr, ntohs(dport));

	currsock.delete(&pid);

	return 0;
}
"""

# initialize BPF
b = BPF(text=bpf_text)

# header
print("%-6s %-12s %-16s %-16s %-4s" % ("PID", "COMM", "SADDR", "DADDR",
    "DPORT"))

def inet_ntoa(addr):
	dq = ''
	for i in range(0, 4):
		dq = dq + str(addr & 0xff)
		if (i != 3):
			dq = dq + '.'
		addr = addr >> 8
	return dq

# filter and format output
while 1:
	# Read messages from kernel pipe
	try:
	    (task, pid, cpu, flags, ts, msg) = b.trace_fields()
	    (_tag, saddr_hs, daddr_hs, dport_s) = msg.split(" ")
	except ValueError:
	    # Ignore messages from other tracers
	    continue

	# Ignore messages from other tracers
	if _tag != "trace_tcp4connect":
	    continue

	print("%-6d %-12.12s %-16s %-16s %-4s" % (pid, task,
	    inet_ntoa(int(saddr_hs, 16)),
	    inet_ntoa(int(daddr_hs, 16)),
	    dport_s))
<|endoftext|>