<commit_before>from enum import Enum

from .definition import (
    GraphQLArgument,
    GraphQLEnumType,
    GraphQLEnumValue,
    GraphQLField,
    GraphQLList,
    GraphQLNamedType,
    GraphQLNonNull,
    GraphQLObjectType,
    is_abstract_type,
    is_enum_type,
    is_input_object_type,
    is_interface_type,
    is_list_type,
    is_non_null_type,
    is_object_type,
    is_scalar_type,
    is_union_type,
)
from ..language import DirectiveLocation, print_ast
from ..pyutils import inspect, FrozenDict
from .scalars import GraphQLBoolean, GraphQLString

__all__ = [
    "SchemaMetaFieldDef",
    "TypeKind",
    "TypeMetaFieldDef",
    "TypeNameMetaFieldDef",
    "introspection_types",
    "is_introspection_type",
]

__Schema: GraphQLObjectType = GraphQLObjectType(
    name="__Schema",
    description="A GraphQL Schema defines the capabilities of a GraphQL"
    " server. It exposes all available types and directives"
    " on the server, as well as the entry points for query,"
    " mutation, and subscription operations.",
    fields=lambda: {
        "types": GraphQLField(
            GraphQLNonNull(GraphQLList(GraphQLNonNull(__Type))),
            resolve=lambda schema, _info: schema.type_map.values(),
            description="A list of all types supported by this server.",
        ),
        "queryType": GraphQLField(
            GraphQLNonNull(__Type),
            resolve=lambda schema, _info: schema.query_type,
            description="The type that query operations will be rooted at.",
        ),
        "mutationType": GraphQLField(
            __Type,
            resolve=lambda schema, _info: schema.mutation_type,
            description="If this server supports mutation, the type that"
            " mutation operations will be rooted at.",
        ),
        "subscriptionType": GraphQLField(
            __Type,
            resolve=lambda schema, _info: schema.subscription_type,
            description="If this server support subscription, the type that"
            " subscription operations will be rooted at.",
        ),
        "directives": GraphQLField(
            GraphQLNonNull(GraphQLList(GraphQLNonNull(__Directive))),
            resolve=lambda schema, _info: schema.directives,
            description="A list of all directives supported by this server.",
        ),
    },
)

__Directive: GraphQLObjectType = GraphQLObjectType(
    name="__Directive",
    description="A Directive provides a way to describe alternate runtime"
    " execution and type validation behavior in a GraphQL"
    " document.\n\nIn some cases, you need to provide options"
    " to alter GraphQL's execution behavior in ways field"
    " arguments will not suffice, such as conditionally including"
    " or skipping a field. Directives provide this by describing"
    " additional information to the executor.",
    fields=lambda: {
        # Note: The fields onOperation, onFragment and onField are deprecated
        "name": GraphQLField(
            GraphQLNonNull(GraphQLString), resolve=lambda obj, _info: obj.name
        ),
        "description": GraphQLField(
            GraphQLString, resolve=lambda obj, _info: obj.description
        ),
        "isRepeatable": GraphQLField(
            GraphQLNonNull(GraphQLBoolean),
            resolve=lambda obj, _info: obj.is_repeatable,
        ),
        "locations": GraphQLField(
            GraphQLNonNull(GraphQLList(GraphQLNonNull(__DirectiveLocation))),
            resolve=lambda obj, _info: obj.locations,
        ),
        "args": GraphQLField(
            GraphQLNonNull(GraphQLList(GraphQLNonNull(__InputValue))),
            resolve=lambda directive, _info: directive.args.items(),
        ),
    },
)

__DirectiveLocation: GraphQLEnumType = GraphQLEnumType(
    name="__DirectiveLocation",
    description="A Directive can be adjacent to many parts of the GraphQL"
    " language, a __DirectiveLocation describes one such possible"
    " adjacencies.",
    values={
        "QUERY": GraphQLEnumValue(
            DirectiveLocation.QUERY,
            description="Location adjacent to a query operation.",
        ),
        "MUTATION": GraphQLEnumValue(
            DirectiveLocation.MUTATION,
            description="Location adjacent to a mutation operation.",
        ),
        "SUBSCRIPTION": GraphQLEnumValue(
            DirectiveLocation.SUBSCRIPTION,
            description="Location adjacent to a subscription operation.",
        ),
        "FIELD": GraphQLEnumValue(
            DirectiveLocation.FIELD, description="Location adjacent to a field."
        ),
        "FRAGMENT_DEFINITION": GraphQLEnumValue(
            DirectiveLocation.FRAGMENT_DEFINITION,
            description="Location adjacent to a fragment definition.",
        ),
        "FRAGMENT_SPREAD": GraphQLEnumValue(
            DirectiveLocation.FRAGMENT_SPREAD,
            description="Location adjacent to a fragment spread.",
        ),
        "INLINE_FRAGMENT": GraphQLEnumValue(
            DirectiveLocation.INLINE_FRAGMENT,
            description="Location adjacent to an inline fragment.",
        ),
        "VARIABLE_DEFINITION": GraphQLEnumValue(
            DirectiveLocation.VARIABLE_DEFINITION,
            description="Location adjacent to a variable definition.",
        ),
        "SCHEMA": GraphQLEnumValue(
            DirectiveLocation.SCHEMA,
            description="Location adjacent to a schema definition.",
        ),
        "SCALAR": GraphQLEnumValue(
            DirectiveLocation.SCALAR,
            description="Location adjacent to a scalar definition.",
        ),
        "OBJECT": GraphQLEnumValue(
            DirectiveLocation.OBJECT,
            description="Location adjacent to an object type definition.",
        ),
        "FIELD_DEFINITION": GraphQLEnumValue(
            DirectiveLocation.FIELD_DEFINITION,
            description="Location adjacent to a field definition.",
        ),
        "ARGUMENT_DEFINITION": GraphQLEnumValue(
            DirectiveLocation.ARGUMENT_DEFINITION,
            description="Location adjacent to an argument definition.",
        ),
        "INTERFACE": GraphQLEnumValue(
            DirectiveLocation.INTERFACE,
            description="Location adjacent to an interface definition.",
        ),
        "UNION": GraphQLEnumValue(
            DirectiveLocation.UNION,
            description="Location adjacent to a union definition.",
        ),
        "ENUM": GraphQLEnumValue(
            DirectiveLocation.ENUM,
            description="Location adjacent to an enum definition.",
        ),
        "ENUM_VALUE": GraphQLEnumValue(
            DirectiveLocation.ENUM_VALUE,
            description="Location adjacent to an enum value definition.",
        ),
        "INPUT_OBJECT": GraphQLEnumValue(
            DirectiveLocation.INPUT_OBJECT,
            description="Location adjacent to an input object type definition.",
        ),
        "INPUT_FIELD_DEFINITION": GraphQLEnumValue(
            DirectiveLocation.INPUT_FIELD_DEFINITION,
            description="Location adjacent to an input object field definition.",
        ),
    },
)

__Type: GraphQLObjectType = GraphQLObjectType(
    name="__Type",
    description="The fundamental unit of any GraphQL Schema is the type."
    " There are many kinds of types in GraphQL as represented"
    " by the `__TypeKind` enum.\n\nDepending on the kind of a"
    " type, certain fields describe information about that type."
    " Scalar types provide no information beyond a name and"
    " description, while Enum types provide their values."
    " Object and Interface types provide the fields they describe."
    " Abstract types, Union and Interface, provide the Object"
    " types possible at runtime. List and NonNull types compose"
    " other types.",
    fields=lambda: {
        "kind": GraphQLField(
            GraphQLNonNull(__TypeKind), resolve=TypeFieldResolvers.kind
        ),
        "name": GraphQLField(GraphQLString, resolve=TypeFieldResolvers.name),
        "description": GraphQLField(
            GraphQLString, resolve=TypeFieldResolvers.description
        ),
        "fields": GraphQLField(
            GraphQLList(GraphQLNonNull(__Field)),
            args={
                "includeDeprecated": GraphQLArgument(
                    GraphQLBoolean, default_value=False
                )
            },
            resolve=TypeFieldResolvers.fields,
        ),
        "interfaces": GraphQLField(
            GraphQLList(GraphQLNonNull(__Type)), resolve=TypeFieldResolvers.interfaces
        ),
        "possibleTypes": GraphQLField(
            GraphQLList(GraphQLNonNull(__Type)),
            resolve=TypeFieldResolvers.possible_types,
        ),
        "enumValues": GraphQLField(
            GraphQLList(GraphQLNonNull(__EnumValue)),
            args={
                "includeDeprecated": GraphQLArgument(
                    GraphQLBoolean, default_value=False
                )
            },
            resolve=TypeFieldResolvers.enum_values,
        ),
        "inputFields": GraphQLField(
            GraphQLList(GraphQLNonNull(__InputValue)),
            resolve=TypeFieldResolvers.input_fields,
        ),
        "ofType": GraphQLField(__Type, resolve=TypeFieldResolvers.of_type),
    },
)

class TypeFieldResolvers:
    @staticmethod
    def kind(type_, _info):
        if is_scalar_type(type_):
            return TypeKind.SCALAR
        if is_object_type(type_):
            return TypeKind.OBJECT
        if is_interface_type(type_):
            return TypeKind.INTERFACE
        if is_union_type(type_):
            return TypeKind.UNION
        if is_enum_type(type_):
            return TypeKind.ENUM
        if is_input_object_type(type_):
            return TypeKind.INPUT_OBJECT
        if is_list_type(type_):
            return TypeKind.LIST
        if is_non_null_type(type_):
            return TypeKind.NON_NULL

        # Not reachable. All possible types have been considered.
        raise TypeError(f"Unexpected type: {inspect(type_)}.")  # pragma: no cover

    @staticmethod
    def name(type_, _info):
        return getattr(type_, "name", None)

    @staticmethod
    def description(type_, _info):
        return getattr(type_, "description", None)

    # noinspection PyPep8Naming
    @staticmethod
    def fields(type_, _info, includeDeprecated=False):
        if is_object_type(type_) or is_interface_type(type_):
            items = type_.fields.items()
            if not includeDeprecated:
                return [item for item in items if not item[1].is_deprecated]
            return list(items)

    @staticmethod
    def interfaces(type_, _info):
        if is_object_type(type_) or is_interface_type(type_):
            return type_.interfaces

    @staticmethod
    def possible_types(type_, info):
        if is_abstract_type(type_):
            return info.schema.get_possible_types(type_)

    # noinspection PyPep8Naming
    @staticmethod
    def enum_values(type_, _info, includeDeprecated=False):
        if is_enum_type(type_):
            items = type_.values.items()
            if not includeDeprecated:
                return [item for item in items if not item[1].is_deprecated]
            return items

    @staticmethod
    def input_fields(type_, _info):
        if is_input_object_type(type_):
            return type_.fields.items()

    @staticmethod
    def of_type(type_, _info):
        return getattr(type_, "of_type", None)

__Field: GraphQLObjectType = GraphQLObjectType(
    name="__Field",
    description="Object and Interface types are described by a list of Fields,"
    " each of which has a name, potentially a list of arguments,"
    " and a return type.",
    fields=lambda: {
        "name": GraphQLField(
            GraphQLNonNull(GraphQLString), resolve=lambda item, _info: item[0]
        ),
        "description": GraphQLField(
            GraphQLString, resolve=lambda item, _info: item[1].description
        ),
        "args": GraphQLField(
            GraphQLNonNull(GraphQLList(GraphQLNonNull(__InputValue))),
            resolve=lambda item, _info: item[1].args.items(),
        ),
        "type": GraphQLField(
            GraphQLNonNull(__Type), resolve=lambda item, _info: item[1].type
        ),
        "isDeprecated": GraphQLField(
            GraphQLNonNull(GraphQLBoolean),
            resolve=lambda item, _info: item[1].is_deprecated,
        ),
        "deprecationReason": GraphQLField(
            GraphQLString, resolve=lambda item, _info: item[1].deprecation_reason
        ),
    },
)

__InputValue: GraphQLObjectType = GraphQLObjectType(
    name="__InputValue",
    description="Arguments provided to Fields or Directives and the input"
    " fields of an InputObject are represented as Input Values"
    " which describe their type and optionally a default value.",
    fields=lambda: {
        "name": GraphQLField(
            GraphQLNonNull(GraphQLString), resolve=InputValueFieldResolvers.name
        ),
        "description": GraphQLField(
            GraphQLString, resolve=InputValueFieldResolvers.description
        ),
        "type": GraphQLField(
            GraphQLNonNull(__Type), resolve=InputValueFieldResolvers.type
        ),
        "defaultValue": GraphQLField(
            GraphQLString,
            description="A GraphQL-formatted string representing"
            " the default value for this input value.",
            resolve=InputValueFieldResolvers.default_value,
        ),
    },
)

class InputValueFieldResolvers:
    @staticmethod
    def name(item, _info):
        return item[0]

    @staticmethod
    def description(item, _info):
        return item[1].description

    @staticmethod
    def type(item, _info):
        return item[1].type

    @staticmethod
    def default_value(item, _info):
        # Since ast_from_value needs graphql.type, it can only be imported later
        from ..utilities import ast_from_value

        value_ast = ast_from_value(item[1].default_value, item[1].type)
        return print_ast(value_ast) if value_ast else None

__EnumValue: GraphQLObjectType = GraphQLObjectType(
    name="__EnumValue",
    description="One possible value for a given Enum. Enum values are unique"
    " values, not a placeholder for a string or numeric value."
    " However an Enum value is returned in a JSON response as a"
    " string.",
    fields=lambda: {
        "name": GraphQLField(
            GraphQLNonNull(GraphQLString), resolve=lambda item, _info: item[0]
        ),
        "description": GraphQLField(
            GraphQLString, resolve=lambda item, _info: item[1].description
        ),
        "isDeprecated": GraphQLField(
            GraphQLNonNull(GraphQLBoolean),
            resolve=lambda item, _info: item[1].is_deprecated,
        ),
        "deprecationReason": GraphQLField(
            GraphQLString, resolve=lambda item, _info: item[1].deprecation_reason
        ),
    },
)

class TypeKind(Enum):
    SCALAR = "scalar"
    OBJECT = "object"
    INTERFACE = "interface"
    UNION = "union"
    ENUM = "enum"
    INPUT_OBJECT = "input object"
    LIST = "list"
    NON_NULL = "non-null"

__TypeKind: GraphQLEnumType = GraphQLEnumType(
    name="__TypeKind",
    description="An enum describing what kind of type a given `__Type` is.",
    values={
        "SCALAR": GraphQLEnumValue(
            TypeKind.SCALAR, description="Indicates this type is a scalar."
        ),
        "OBJECT": GraphQLEnumValue(
            TypeKind.OBJECT,
            description="Indicates this type is an object."
            " `fields` and `interfaces` are valid fields.",
        ),
        "INTERFACE": GraphQLEnumValue(
            TypeKind.INTERFACE,
            description="Indicates this type is an interface."
            " `fields`, `interfaces`, and `possibleTypes` are valid fields.",
        ),
        "UNION": GraphQLEnumValue(
            TypeKind.UNION,
            description="Indicates this type is a union."
            " `possibleTypes` is a valid field.",
        ),
        "ENUM": GraphQLEnumValue(
            TypeKind.ENUM,
            description="Indicates this type is an enum."
            " `enumValues` is a valid field.",
        ),
        "INPUT_OBJECT": GraphQLEnumValue(
            TypeKind.INPUT_OBJECT,
            description="Indicates this type is an input object."
            " `inputFields` is a valid field.",
        ),
        "LIST": GraphQLEnumValue(
            TypeKind.LIST,
            description="Indicates this type is a list. `ofType` is a valid field.",
        ),
        "NON_NULL": GraphQLEnumValue(
            TypeKind.NON_NULL,
            description="Indicates this type is a non-null."
            " `ofType` is a valid field.",
        ),
    },
)

SchemaMetaFieldDef = GraphQLField(
    GraphQLNonNull(__Schema),  # name = '__schema'
    description="Access the current type schema of this server.",
    args={},
    resolve=lambda _source, info: info.schema,
)

TypeMetaFieldDef = GraphQLField(
    __Type,  # name = '__type'
    description="Request the type information of a single type.",
    args={"name": GraphQLArgument(GraphQLNonNull(GraphQLString))},
    resolve=lambda _source, info, **args: info.schema.get_type(args["name"]),
)

TypeNameMetaFieldDef = GraphQLField(
    GraphQLNonNull(GraphQLString),  # name='__typename'
    description="The name of the current Object type at runtime.",
    args={},
    resolve=lambda _source, info, **_args: info.parent_type.name,
)

# Since double underscore names are subject to name mangling in Python,
# the introspection classes are best imported via this dictionary:
introspection_types = FrozenDict(
    {
        "__Schema": __Schema,
        "__Directive": __Directive,
        "__DirectiveLocation": __DirectiveLocation,
        "__Type": __Type,
        "__Field": __Field,
        "__InputValue": __InputValue,
        "__EnumValue": __EnumValue,
        "__TypeKind": __TypeKind,
    }
)
introspection_types.__doc__ = """A dictionary containing all introspection types."""

def is_introspection_type(type_: GraphQLNamedType) -> bool:
    """Check whether the given named GraphQL type is an introspection type."""
    return type_.name in introspection_types
<commit_msg>introspection: use consistent naming for 'resolve' args<commit_after>from enum import Enum

from .definition import (
    GraphQLArgument,
    GraphQLEnumType,
    GraphQLEnumValue,
    GraphQLField,
    GraphQLList,
    GraphQLNamedType,
    GraphQLNonNull,
    GraphQLObjectType,
    is_abstract_type,
    is_enum_type,
    is_input_object_type,
    is_interface_type,
    is_list_type,
    is_non_null_type,
    is_object_type,
    is_scalar_type,
    is_union_type,
)
from ..language import DirectiveLocation, print_ast
from ..pyutils import inspect, FrozenDict
from .scalars import GraphQLBoolean, GraphQLString

__all__ = [
    "SchemaMetaFieldDef",
    "TypeKind",
    "TypeMetaFieldDef",
    "TypeNameMetaFieldDef",
    "introspection_types",
    "is_introspection_type",
]

__Schema: GraphQLObjectType = GraphQLObjectType(
    name="__Schema",
    description="A GraphQL Schema defines the capabilities of a GraphQL"
    " server. It exposes all available types and directives"
    " on the server, as well as the entry points for query,"
    " mutation, and subscription operations.",
    fields=lambda: {
        "types": GraphQLField(
            GraphQLNonNull(GraphQLList(GraphQLNonNull(__Type))),
            resolve=lambda schema, _info: schema.type_map.values(),
            description="A list of all types supported by this server.",
        ),
        "queryType": GraphQLField(
            GraphQLNonNull(__Type),
            resolve=lambda schema, _info: schema.query_type,
            description="The type that query operations will be rooted at.",
        ),
        "mutationType": GraphQLField(
            __Type,
            resolve=lambda schema, _info: schema.mutation_type,
            description="If this server supports mutation, the type that"
            " mutation operations will be rooted at.",
        ),
        "subscriptionType": GraphQLField(
            __Type,
            resolve=lambda schema, _info: schema.subscription_type,
            description="If this server support subscription, the type that"
            " subscription operations will be rooted at.",
        ),
        "directives": GraphQLField(
            GraphQLNonNull(GraphQLList(GraphQLNonNull(__Directive))),
            resolve=lambda schema, _info: schema.directives,
            description="A list of all directives supported by this server.",
        ),
    },
)

__Directive: GraphQLObjectType = GraphQLObjectType(
    name="__Directive",
    description="A Directive provides a way to describe alternate runtime"
    " execution and type validation behavior in a GraphQL"
    " document.\n\nIn some cases, you need to provide options"
    " to alter GraphQL's execution behavior in ways field"
    " arguments will not suffice, such as conditionally including"
    " or skipping a field. Directives provide this by describing"
    " additional information to the executor.",
    fields=lambda: {
        # Note: The fields onOperation, onFragment and onField are deprecated
        "name": GraphQLField(
            GraphQLNonNull(GraphQLString),
            resolve=lambda directive, _info: directive.name,
        ),
        "description": GraphQLField(
            GraphQLString, resolve=lambda directive, _info: directive.description
        ),
        "isRepeatable": GraphQLField(
            GraphQLNonNull(GraphQLBoolean),
            resolve=lambda directive, _info: directive.is_repeatable,
        ),
        "locations": GraphQLField(
            GraphQLNonNull(GraphQLList(GraphQLNonNull(__DirectiveLocation))),
            resolve=lambda directive, _info: directive.locations,
        ),
        "args": GraphQLField(
            GraphQLNonNull(GraphQLList(GraphQLNonNull(__InputValue))),
            resolve=lambda directive, _info: directive.args.items(),
        ),
    },
)

__DirectiveLocation: GraphQLEnumType = GraphQLEnumType(
    name="__DirectiveLocation",
    description="A Directive can be adjacent to many parts of the GraphQL"
    " language, a __DirectiveLocation describes one such possible"
    " adjacencies.",
    values={
        "QUERY": GraphQLEnumValue(
            DirectiveLocation.QUERY,
            description="Location adjacent to a query operation.",
        ),
        "MUTATION": GraphQLEnumValue(
            DirectiveLocation.MUTATION,
            description="Location adjacent to a mutation operation.",
        ),
        "SUBSCRIPTION": GraphQLEnumValue(
            DirectiveLocation.SUBSCRIPTION,
            description="Location adjacent to a subscription operation.",
        ),
        "FIELD": GraphQLEnumValue(
            DirectiveLocation.FIELD, description="Location adjacent to a field."
        ),
        "FRAGMENT_DEFINITION": GraphQLEnumValue(
            DirectiveLocation.FRAGMENT_DEFINITION,
            description="Location adjacent to a fragment definition.",
        ),
        "FRAGMENT_SPREAD": GraphQLEnumValue(
            DirectiveLocation.FRAGMENT_SPREAD,
            description="Location adjacent to a fragment spread.",
        ),
        "INLINE_FRAGMENT": GraphQLEnumValue(
            DirectiveLocation.INLINE_FRAGMENT,
            description="Location adjacent to an inline fragment.",
        ),
        "VARIABLE_DEFINITION": GraphQLEnumValue(
            DirectiveLocation.VARIABLE_DEFINITION,
            description="Location adjacent to a variable definition.",
        ),
        "SCHEMA": GraphQLEnumValue(
            DirectiveLocation.SCHEMA,
            description="Location adjacent to a schema definition.",
        ),
        "SCALAR": GraphQLEnumValue(
            DirectiveLocation.SCALAR,
            description="Location adjacent to a scalar definition.",
        ),
        "OBJECT": GraphQLEnumValue(
            DirectiveLocation.OBJECT,
            description="Location adjacent to an object type definition.",
        ),
        "FIELD_DEFINITION": GraphQLEnumValue(
            DirectiveLocation.FIELD_DEFINITION,
            description="Location adjacent to a field definition.",
        ),
        "ARGUMENT_DEFINITION": GraphQLEnumValue(
            DirectiveLocation.ARGUMENT_DEFINITION,
            description="Location adjacent to an argument definition.",
        ),
        "INTERFACE": GraphQLEnumValue(
            DirectiveLocation.INTERFACE,
            description="Location adjacent to an interface definition.",
        ),
        "UNION": GraphQLEnumValue(
            DirectiveLocation.UNION,
            description="Location adjacent to a union definition.",
        ),
        "ENUM": GraphQLEnumValue(
            DirectiveLocation.ENUM,
            description="Location adjacent to an enum definition.",
        ),
        "ENUM_VALUE": GraphQLEnumValue(
            DirectiveLocation.ENUM_VALUE,
            description="Location adjacent to an enum value definition.",
        ),
        "INPUT_OBJECT": GraphQLEnumValue(
            DirectiveLocation.INPUT_OBJECT,
            description="Location adjacent to an input object type definition.",
        ),
        "INPUT_FIELD_DEFINITION": GraphQLEnumValue(
            DirectiveLocation.INPUT_FIELD_DEFINITION,
            description="Location adjacent to an input object field definition.",
        ),
    },
)

__Type: GraphQLObjectType = GraphQLObjectType(
    name="__Type",
    description="The fundamental unit of any GraphQL Schema is the type."
    " There are many kinds of types in GraphQL as represented"
    " by the `__TypeKind` enum.\n\nDepending on the kind of a"
    " type, certain fields describe information about that type."
    " Scalar types provide no information beyond a name and"
    " description, while Enum types provide their values."
    " Object and Interface types provide the fields they describe."
    " Abstract types, Union and Interface, provide the Object"
    " types possible at runtime. List and NonNull types compose"
    " other types.",
    fields=lambda: {
        "kind": GraphQLField(
            GraphQLNonNull(__TypeKind), resolve=TypeFieldResolvers.kind
        ),
        "name": GraphQLField(GraphQLString, resolve=TypeFieldResolvers.name),
        "description": GraphQLField(
            GraphQLString, resolve=TypeFieldResolvers.description
        ),
        "fields": GraphQLField(
            GraphQLList(GraphQLNonNull(__Field)),
            args={
                "includeDeprecated": GraphQLArgument(
                    GraphQLBoolean, default_value=False
                )
            },
            resolve=TypeFieldResolvers.fields,
        ),
        "interfaces": GraphQLField(
            GraphQLList(GraphQLNonNull(__Type)), resolve=TypeFieldResolvers.interfaces
        ),
        "possibleTypes": GraphQLField(
            GraphQLList(GraphQLNonNull(__Type)),
            resolve=TypeFieldResolvers.possible_types,
        ),
        "enumValues": GraphQLField(
            GraphQLList(GraphQLNonNull(__EnumValue)),
            args={
                "includeDeprecated": GraphQLArgument(
                    GraphQLBoolean, default_value=False
                )
            },
            resolve=TypeFieldResolvers.enum_values,
        ),
        "inputFields": GraphQLField(
            GraphQLList(GraphQLNonNull(__InputValue)),
            resolve=TypeFieldResolvers.input_fields,
        ),
        "ofType": GraphQLField(__Type, resolve=TypeFieldResolvers.of_type),
    },
)

class TypeFieldResolvers:
    @staticmethod
    def kind(type_, _info):
        if is_scalar_type(type_):
            return TypeKind.SCALAR
        if is_object_type(type_):
            return TypeKind.OBJECT
        if is_interface_type(type_):
            return TypeKind.INTERFACE
        if is_union_type(type_):
            return TypeKind.UNION
        if is_enum_type(type_):
            return TypeKind.ENUM
        if is_input_object_type(type_):
            return TypeKind.INPUT_OBJECT
        if is_list_type(type_):
            return TypeKind.LIST
        if is_non_null_type(type_):
            return TypeKind.NON_NULL

        # Not reachable. All possible types have been considered.
        raise TypeError(f"Unexpected type: {inspect(type_)}.")  # pragma: no cover

    @staticmethod
    def name(type_, _info):
        return getattr(type_, "name", None)

    @staticmethod
    def description(type_, _info):
        return getattr(type_, "description", None)

    # noinspection PyPep8Naming
    @staticmethod
    def fields(type_, _info, includeDeprecated=False):
        if is_object_type(type_) or is_interface_type(type_):
            items = type_.fields.items()
            if not includeDeprecated:
                return [item for item in items if not item[1].is_deprecated]
            return list(items)

    @staticmethod
    def interfaces(type_, _info):
        if is_object_type(type_) or is_interface_type(type_):
            return type_.interfaces

    @staticmethod
    def possible_types(type_, info):
        if is_abstract_type(type_):
            return info.schema.get_possible_types(type_)

    # noinspection PyPep8Naming
    @staticmethod
    def enum_values(type_, _info, includeDeprecated=False):
        if is_enum_type(type_):
            items = type_.values.items()
            if not includeDeprecated:
                return [item for item in items if not item[1].is_deprecated]
            return items

    @staticmethod
    def input_fields(type_, _info):
        if is_input_object_type(type_):
            return type_.fields.items()

    @staticmethod
    def of_type(type_, _info):
        return getattr(type_, "of_type", None)

__Field: GraphQLObjectType = GraphQLObjectType(
    name="__Field",
    description="Object and Interface types are described by a list of Fields,"
    " each of which has a name, potentially a list of arguments,"
    " and a return type.",
    fields=lambda: {
        "name": GraphQLField(
            GraphQLNonNull(GraphQLString), resolve=lambda item, _info: item[0]
        ),
        "description": GraphQLField(
            GraphQLString, resolve=lambda item, _info: item[1].description
        ),
        "args": GraphQLField(
            GraphQLNonNull(GraphQLList(GraphQLNonNull(__InputValue))),
            resolve=lambda item, _info: item[1].args.items(),
        ),
        "type": GraphQLField(
            GraphQLNonNull(__Type), resolve=lambda item, _info: item[1].type
        ),
        "isDeprecated": GraphQLField(
            GraphQLNonNull(GraphQLBoolean),
            resolve=lambda item, _info: item[1].is_deprecated,
        ),
        "deprecationReason": GraphQLField(
            GraphQLString, resolve=lambda item, _info: item[1].deprecation_reason
        ),
    },
)

__InputValue: GraphQLObjectType = GraphQLObjectType(
    name="__InputValue",
    description="Arguments provided to Fields or Directives and the input"
    " fields of an InputObject are represented as Input Values"
    " which describe their type and optionally a default value.",
    fields=lambda: {
        "name": GraphQLField(
            GraphQLNonNull(GraphQLString), resolve=InputValueFieldResolvers.name
        ),
        "description": GraphQLField(
            GraphQLString, resolve=InputValueFieldResolvers.description
        ),
        "type": GraphQLField(
            GraphQLNonNull(__Type), resolve=InputValueFieldResolvers.type
        ),
        "defaultValue": GraphQLField(
            GraphQLString,
            description="A GraphQL-formatted string representing"
            " the default value for this input value.",
            resolve=InputValueFieldResolvers.default_value,
        ),
    },
)

class InputValueFieldResolvers:
    @staticmethod
    def name(item, _info):
        return item[0]

    @staticmethod
    def description(item, _info):
        return item[1].description

    @staticmethod
    def type(item, _info):
        return item[1].type

    @staticmethod
    def default_value(item, _info):
        # Since ast_from_value needs graphql.type, it can only be imported later
        from ..utilities import ast_from_value

        value_ast = ast_from_value(item[1].default_value, item[1].type)
        return print_ast(value_ast) if value_ast else None

__EnumValue: GraphQLObjectType = GraphQLObjectType(
    name="__EnumValue",
    description="One possible value for a given Enum. Enum values are unique"
    " values, not a placeholder for a string or numeric value."
    " However an Enum value is returned in a JSON response as a"
    " string.",
    fields=lambda: {
        "name": GraphQLField(
            GraphQLNonNull(GraphQLString), resolve=lambda item, _info: item[0]
        ),
        "description": GraphQLField(
            GraphQLString, resolve=lambda item, _info: item[1].description
        ),
        "isDeprecated": GraphQLField(
            GraphQLNonNull(GraphQLBoolean),
            resolve=lambda item, _info: item[1].is_deprecated,
        ),
        "deprecationReason": GraphQLField(
            GraphQLString, resolve=lambda item, _info: item[1].deprecation_reason
        ),
    },
)

class TypeKind(Enum):
    SCALAR = "scalar"
    OBJECT = "object"
    INTERFACE = "interface"
    UNION = "union"
    ENUM = "enum"
    INPUT_OBJECT = "input object"
    LIST = "list"
    NON_NULL = "non-null"

__TypeKind: GraphQLEnumType = GraphQLEnumType(
    name="__TypeKind",
    description="An enum describing what kind of type a given `__Type` is.",
    values={
        "SCALAR": GraphQLEnumValue(
            TypeKind.SCALAR, description="Indicates this type is a scalar."
        ),
        "OBJECT": GraphQLEnumValue(
            TypeKind.OBJECT,
            description="Indicates this type is an object."
            " `fields` and `interfaces` are valid fields.",
        ),
        "INTERFACE": GraphQLEnumValue(
            TypeKind.INTERFACE,
            description="Indicates this type is an interface."
            " `fields`, `interfaces`, and `possibleTypes` are valid fields.",
        ),
        "UNION": GraphQLEnumValue(
            TypeKind.UNION,
            description="Indicates this type is a union."
            " `possibleTypes` is a valid field.",
        ),
        "ENUM": GraphQLEnumValue(
            TypeKind.ENUM,
            description="Indicates this type is an enum."
            " `enumValues` is a valid field.",
        ),
        "INPUT_OBJECT": GraphQLEnumValue(
            TypeKind.INPUT_OBJECT,
            description="Indicates this type is an input object."
            " `inputFields` is a valid field.",
        ),
        "LIST": GraphQLEnumValue(
            TypeKind.LIST,
            description="Indicates this type is a list. `ofType` is a valid field.",
        ),
        "NON_NULL": GraphQLEnumValue(
            TypeKind.NON_NULL,
            description="Indicates this type is a non-null."
            " `ofType` is a valid field.",
        ),
    },
)

SchemaMetaFieldDef = GraphQLField(
    GraphQLNonNull(__Schema),  # name = '__schema'
    description="Access the current type schema of this server.",
    args={},
    resolve=lambda _source, info: info.schema,
)

TypeMetaFieldDef = GraphQLField(
    __Type,  # name = '__type'
    description="Request the type information of a single type.",
    args={"name": GraphQLArgument(GraphQLNonNull(GraphQLString))},
    resolve=lambda _source, info, **args: info.schema.get_type(args["name"]),
)

TypeNameMetaFieldDef = GraphQLField(
    GraphQLNonNull(GraphQLString),  # name='__typename'
    description="The name of the current Object type at runtime.",
    args={},
    resolve=lambda _source, info, **_args: info.parent_type.name,
)

# Since double underscore names are subject to name mangling in Python,
# the introspection classes are best imported via this dictionary:
introspection_types = FrozenDict(
    {
        "__Schema": __Schema,
        "__Directive": __Directive,
        "__DirectiveLocation": __DirectiveLocation,
        "__Type": __Type,
        "__Field": __Field,
        "__InputValue": __InputValue,
        "__EnumValue": __EnumValue,
        "__TypeKind": __TypeKind,
    }
)
introspection_types.__doc__ = """A dictionary containing all introspection types."""

def is_introspection_type(type_: GraphQLNamedType) -> bool:
    """Check whether the given named GraphQL type is an introspection type."""
    return type_.name in introspection_types
<|endoftext|>


<commit_before>import re

class Match(object):
	def __init__(self):
		self.error_pages = set()

	def _check_page(self, response, fingerprint):

		# check if the page is a 404
		is_404 = response.status['code'] == 404 or response.md5_404 in self.error_pages

		# fingerprints that do not have a 'code' set, default to 200
		# find the 'code' of the current fingerprint
		fp_code = 200 if not 'code' in fingerprint else fingerprint['code']

		if fp_code == 'any':
			return True

		# if the fingerprint is for a 404 but the page is not a 404, do not match
		elif (not is_404) and fp_code == 404:
			return False

		# if the page is a 404 but the fingerprint is not for a 404, do not match
		elif is_404 and (not fp_code == 404):
			return False

		# else match
		else:
			return True

	def set_404s(self, set_of_404s):
		self.error_pages = set_of_404s

	def get_result(self, fingerprints, response):
		# find the matching method to use
		matches = []

		# find out of the reponse is an image
		# this is used to avoid the crawler using string and regex
		# searching for matches in these files
		content_type = 'Content-Type'.lower()
		if content_type in response.headers:
			is_image = 'image' in response.headers[content_type]

		# default to the content being an image, since if the content-type
		# isn't set, the content is unknown
		else:
			is_image = True

		for fingerprint in fingerprints:

			# only check the page if the status codes match
			if not self._check_page(response, fingerprint):
				matches.append(None)

			elif fingerprint['type'] == 'md5':
				matches.append(self.md5(fingerprint, response))

			elif fingerprint['type'] == 'string' and not is_image:
				matches.append(self.string(fingerprint, response))

			elif fingerprint['type'] == 'regex' and not is_image:
				matches.append(self.regex(fingerprint, response))

			elif fingerprint['type'] == 'header':
				matches.append(self.header(fingerprint, response))

			else:
				# fingerprint type is not supported yet
				matches.append(None)

		matches = [fp for fp in matches if fp is not None]

		return matches

	def md5(self, fingerprint, response):
		if fingerprint["md5"] == response.md5:
			return fingerprint
		else:
			return None

	def string(self, fingerprint, response):
		if fingerprint["string"] in response.body:
			return fingerprint
		else:
			return None

	def regex(self, fingerprint, response):
		# create copy of fingerprint
		copy = {key:fingerprint[key] for key in fingerprint}

		regex = copy["regex"]
		output = copy["output"]

		matches = re.findall(regex, response.body)
		if len(matches):
			if not output == "":
				copy['output'] = output % matches[0]

			return copy
		else:
			return None

	def header(self, fingerprint, response):
		fp_header = fingerprint['header']
		match_type = 'string' if 'string' in fingerprint else 'regex'

		# a dummy class to mimic a response
		class response_dummy(object):
			self.body = ''

		# parse the headers searching for a match
		for header in response.headers:
			if header == fp_header.lower():

				# create an intance of the dummy class
				r = response_dummy()
				r.body = response.headers[header]

				# call the Match instances methods for string or regex matching
				if 'string' in fingerprint:
					return self.string(fingerprint, r)
				else:
					return self.regex(fingerprint, r)

<commit_msg>Improved replacement of output for regex<commit_after>import re

class Match(object):
	def __init__(self):
		self.error_pages = set()

	def _check_page(self, response, fingerprint):

		# check if the page is a 404
		is_404 = response.status['code'] == 404 or response.md5_404 in self.error_pages

		# fingerprints that do not have a 'code' set, default to 200
		# find the 'code' of the current fingerprint
		fp_code = 200 if not 'code' in fingerprint else fingerprint['code']

		if fp_code == 'any':
			return True

		# if the fingerprint is for a 404 but the page is not a 404, do not match
		elif (not is_404) and fp_code == 404:
			return False

		# if the page is a 404 but the fingerprint is not for a 404, do not match
		elif is_404 and (not fp_code == 404):
			return False

		# else match
		else:
			return True

	def set_404s(self, set_of_404s):
		self.error_pages = set_of_404s

	def get_result(self, fingerprints, response):
		# find the matching method to use
		matches = []

		# find out of the reponse is an image
		# this is used to avoid the crawler using string and regex
		# searching for matches in these files
		content_type = 'Content-Type'.lower()
		if content_type in response.headers:
			is_image = 'image' in response.headers[content_type]

		# default to the content being an image, since if the content-type
		# isn't set, the content is unknown
		else:
			is_image = True

		for fingerprint in fingerprints:

			# only check the page if the status codes match
			if not self._check_page(response, fingerprint):
				matches.append(None)

			elif fingerprint['type'] == 'md5':
				matches.append(self.md5(fingerprint, response))

			elif fingerprint['type'] == 'string' and not is_image:
				matches.append(self.string(fingerprint, response))

			elif fingerprint['type'] == 'regex' and not is_image:
				matches.append(self.regex(fingerprint, response))

			elif fingerprint['type'] == 'header':
				matches.append(self.header(fingerprint, response))

			else:
				# fingerprint type is not supported yet
				matches.append(None)

		matches = [fp for fp in matches if fp is not None]

		return matches

	def md5(self, fingerprint, response):
		if fingerprint["md5"] == response.md5:
			return fingerprint
		else:
			return None

	def string(self, fingerprint, response):
		if fingerprint["string"] in response.body:
			return fingerprint
		else:
			return None

	def regex(self, fingerprint, response):
		# create copy of fingerprint
		copy = {key:fingerprint[key] for key in fingerprint}

		regex = copy["regex"]
		output = copy["output"]

		matches = re.findall(regex, response.body)
		if len(matches):
			if "%" in output:
				copy['output'] = output % matches[0]

			return copy
		else:
			return None

	def header(self, fingerprint, response):
		fp_header = fingerprint['header']
		match_type = 'string' if 'string' in fingerprint else 'regex'

		# a dummy class to mimic a response
		class response_dummy(object):
			self.body = ''

		# parse the headers searching for a match
		for header in response.headers:
			if header == fp_header.lower():

				# create an intance of the dummy class
				r = response_dummy()
				r.body = response.headers[header]

				# call the Match instances methods for string or regex matching
				if 'string' in fingerprint:
					return self.string(fingerprint, r)
				else:
					return self.regex(fingerprint, r)

<|endoftext|>


<commit_before>#!/usr/bin/python
# -*- coding: utf-8 -*-
import json
import requests
import os

from Config import Config
from init_logging import log_string
from init_blinkt import blink
from Adafruit_IO import Client

class Update:
    def __init__(self):

        log_string('Run Update module by: {}'.format(self.__class__))

        ###

        self.config = Config().get_config()

        # set the configs
        self.FORECAST_IO_KEY = self.config['FORECAST_IO_KEY']

        # parameter for the request url
        self.FORECAST_URL = 'https://api.forecast.io/forecast/'  # endpoint for the API

        self.LATITUDE = self.config['LATITUDE']
        self.LONGITUDE = self.config['LONGITUDE']

        self.options = '?lang=de&units=si&exclude=flags'  # some options, see details in API documentation

        self.folder_path = '/home/pi/WeatherPi/Modules/Animations/'

        self.version_path = self.config['UNICORN_VERSION'] + '/'

        self.path = self.folder_path + self.version_path

        self.icon_extension = '.' + 'png'

        self.ADAFRUIT_IO_KEY_SENSORS = self.config['ADAFRUIT_IO_KEY_SENSORS']

        self.aio_sensors = Client(self.ADAFRUIT_IO_KEY_SENSORS)

        try:
            self.data = open('/home/pi/WeatherPi/logs/test_weather_with_alarm.json').read()
            # self.data = open('/home/pi/WeatherPi/logs/latest_weather.json').read()

            self.json_data = json.loads(self.data)

            self.temp_api = self.json_data['currently']['temperature']
            self.sensor_temp_outside = self.json_data['currently']['sensor_temp_outside']
            self.sensor_temp_inside = self.json_data['currently']['sensor_temp_inside']

            self.sensor_pressure_outside = self.json_data['currently']['sensor_pressure_outside']
            self.sensor_humidity_outside = self.json_data['currently']['sensor_humidity_outside']

            self.sensor_pressure_inside = self.json_data['currently']['sensor_pressure_inside']
            self.sensor_humidity_inside = self.json_data['currently']['sensor_humidity_inside']

            self.rain_percentage_data = self.json_data['currently']['precipProbability']
            self.rain_percentage = self.rain_percentage_data * 100

            self.forecast = self.json_data['currently']['summary'].encode('UTF-8')

            self.hourly_data = self.json_data['hourly']['data']

            self.daily = self.json_data['daily']['data']
            self.forecast_today = self.daily[0]

            self.temp_range_today_min = int(self.forecast_today['temperatureMin'])
            self.temp_range_today_max = int(self.forecast_today['temperatureMax'])

            self.hourly_forecast = self.json_data['hourly']['summary']

            self.forecast_today = '{} bis {}°C - {}'.format(
                self.temp_range_today_min,
                self.temp_range_today_max,
                self.hourly_forecast.encode('UTF-8')
            )

            self.weather_icon = self.json_data['currently']['icon']

            self.icon_path = self.path + self.weather_icon + self.icon_extension

        except IOError:

            log_string('ERROR - json file read by module'.format(self.__class__))

    def update_json(self):
        log_string('get latest weather from forecast.io')

        request_url = self.FORECAST_URL + self.FORECAST_IO_KEY + '/' + str(self.LATITUDE) + ',' + \
            str(self.LONGITUDE) + self.options  # build it

        log_string('build request url: {}'.format(request_url))

        try:
            log_string('Try to get data online...')
            self.data = requests.get(request_url, timeout=5).json()

            # Do Stuff

            #  get sensor data inside

            sensor_temp_inside = self.aio_sensors.receive('sensortempinside')
            sensor_temp_inside = float(sensor_temp_inside.value)

            log_string('fetched sensortempinside from adafruit.io: {}'.format(sensor_temp_inside))

            sensor_pressure_inside = self.aio_sensors.receive('sensorpressureinside')
            sensor_pressure_inside = float(sensor_pressure_inside.value)

            log_string('fetched sensorpressureinside from adafruit.io: {}'.format(sensor_pressure_inside))

            sensor_humidity_inside = self.aio_sensors.receive('sensorhumidityinside')
            sensor_humidity_inside = float(sensor_humidity_inside.value)

            log_string('fetched sensorhumidityinside from adafruit.io: {}'.format(sensor_humidity_inside))

            #  get sensor data outside

            sensor_temp_outside = self.aio_sensors.receive('sensortempoutside')
            sensor_temp_outside = float(sensor_temp_outside.value)

            log_string('fetched sensortempoutside from adafruit.io: {}'.format(sensor_temp_outside))

            sensor_pressure_outside = self.aio_sensors.receive('sensorpressureoutside')
            sensor_pressure_outside = float(sensor_pressure_outside.value)

            log_string('fetched sensorpressureoutside from adafruit.io: {}'.format(sensor_pressure_outside))

            sensor_humidity_outside = self.aio_sensors.receive('sensorhumidityoutside')
            sensor_humidity_outside = float(sensor_humidity_outside.value)

            log_string('fetched sensorhumidityoutside from adafruit.io: {}'.format(sensor_humidity_outside))

            blink('blue')

            self.data['currently']['sensor_temp_inside'] = sensor_temp_inside
            self.data['currently']['sensor_pressure_inside'] = sensor_pressure_inside
            self.data['currently']['sensor_humidity_inside'] = sensor_humidity_inside

            log_string('added sensor data to temporary json data: '
                       'temp. inside:{} - humidity inside: {} - pressure inside: {}'.format(
                            sensor_temp_inside,
                            sensor_humidity_inside,
                            sensor_pressure_inside
                        ))

            self.data['currently']['sensor_temp_outside'] = sensor_temp_outside
            self.data['currently']['sensor_pressure_outside'] = sensor_pressure_outside
            self.data['currently']['sensor_humidity_outside'] = sensor_humidity_outside

            log_string('added sensor data to temporary json data: '
                       'temp. outside:{} - humidity outside: {} - pressure outside: {}'.format(
                            sensor_temp_outside,
                            sensor_humidity_outside,
                            sensor_pressure_outside
                        ))

            with open('/home/pi/WeatherPi/logs/latest_weather.json', 'w') as outputfile:
                json.dump(self.data, outputfile, indent=2, sort_keys=True)

            with open('/home/pi/WeatherPi/logs/current_weather.json', 'w') as outputfile:
                json.dump(self.data['currently'], outputfile, indent=2, sort_keys=True)

            log_string('json data saved to temporary file')

            os.system('cp /home/pi/WeatherPi/logs/latest_weather.json /var/www/html')
            os.system('cp /home/pi/WeatherPi/logs/current_weather.json /var/www/html')

            log_string('json data copied to /var/www/html')

            blink('white')

        except StandardError:

            log_string('ConnectionError - fallback to cached Data')

if __name__ == '__main__':
    Update().update_json()

<commit_msg>BIG refactoring... and it still works... yeehaa<commit_after>#!/usr/bin/python
# -*- coding: utf-8 -*-
import json
import requests
import os

from Config import Config
from init_logging import log_string
from init_blinkt import blink
from Adafruit_IO import Client

class Update:
    def __init__(self):

        log_string('Run Update module by: {}'.format(self.__class__))

        ###

        self.config = Config().get_config()

        # set the configs
        self.FORECAST_IO_KEY = self.config['FORECAST_IO_KEY']

        # parameter for the request url
        self.FORECAST_URL = 'https://api.forecast.io/forecast/'  # endpoint for the API

        self.LATITUDE = self.config['LATITUDE']
        self.LONGITUDE = self.config['LONGITUDE']

        self.options = '?lang=de&units=si&exclude=flags'  # some options, see details in API documentation

        self.folder_path = '/home/pi/WeatherPi/Modules/Animations/'

        self.version_path = self.config['UNICORN_VERSION'] + '/'

        self.path = self.folder_path + self.version_path

        self.icon_extension = '.' + 'png'

        self.ADAFRUIT_IO_KEY_SENSORS = self.config['ADAFRUIT_IO_KEY_SENSORS']

        self.aio_sensors = Client(self.ADAFRUIT_IO_KEY_SENSORS)

        try:
            # self.data = open('/home/pi/WeatherPi/logs/test_weather_with_alarm.json').read()
            self.data = open('/home/pi/WeatherPi/logs/latest_weather.json').read()

            self.json_data = json.loads(self.data)

            self.temp_api = self.json_data['currently']['temperature']
            self.sensor_temp_outside = self.json_data['currently']['sensor_temp_outside']
            self.sensor_temp_inside = self.json_data['currently']['sensor_temp_inside']

            self.sensor_pressure_outside = self.json_data['currently']['sensor_pressure_outside']
            self.sensor_humidity_outside = self.json_data['currently']['sensor_humidity_outside']

            self.sensor_pressure_inside = self.json_data['currently']['sensor_pressure_inside']
            self.sensor_humidity_inside = self.json_data['currently']['sensor_humidity_inside']

            self.rain_percentage_data = self.json_data['currently']['precipProbability']
            self.rain_percentage = self.rain_percentage_data * 100

            self.forecast = self.json_data['currently']['summary'].encode('UTF-8')

            self.hourly_data = self.json_data['hourly']['data']

            self.daily = self.json_data['daily']['data']
            self.forecast_today = self.daily[0]

            self.temp_range_today_min = int(self.forecast_today['temperatureMin'])
            self.temp_range_today_max = int(self.forecast_today['temperatureMax'])

            self.hourly_forecast = self.json_data['hourly']['summary']

            self.forecast_today = '{} bis {}°C - {}'.format(
                self.temp_range_today_min,
                self.temp_range_today_max,
                self.hourly_forecast.encode('UTF-8')
            )

            self.weather_icon = self.json_data['currently']['icon']

            self.icon_path = self.path + self.weather_icon + self.icon_extension

        except IOError:

            log_string('ERROR - json file read by module'.format(self.__class__))

    def update_json(self):
        log_string('get latest weather from forecast.io')

        request_url = self.FORECAST_URL + self.FORECAST_IO_KEY + '/' + str(self.LATITUDE) + ',' + \
            str(self.LONGITUDE) + self.options  # build it

        log_string('build request url: {}'.format(request_url))

        try:
            log_string('Try to get data online...')
            self.data = requests.get(request_url, timeout=5).json()

            # Do Stuff

            #  get sensor data inside

            sensor_temp_inside = self.aio_sensors.receive('sensortempinside')
            sensor_temp_inside = float(sensor_temp_inside.value)

            log_string('fetched sensortempinside from adafruit.io: {}'.format(sensor_temp_inside))

            sensor_pressure_inside = self.aio_sensors.receive('sensorpressureinside')
            sensor_pressure_inside = float(sensor_pressure_inside.value)

            log_string('fetched sensorpressureinside from adafruit.io: {}'.format(sensor_pressure_inside))

            sensor_humidity_inside = self.aio_sensors.receive('sensorhumidityinside')
            sensor_humidity_inside = float(sensor_humidity_inside.value)

            log_string('fetched sensorhumidityinside from adafruit.io: {}'.format(sensor_humidity_inside))

            #  get sensor data outside

            sensor_temp_outside = self.aio_sensors.receive('sensortempoutside')
            sensor_temp_outside = float(sensor_temp_outside.value)

            log_string('fetched sensortempoutside from adafruit.io: {}'.format(sensor_temp_outside))

            sensor_pressure_outside = self.aio_sensors.receive('sensorpressureoutside')
            sensor_pressure_outside = float(sensor_pressure_outside.value)

            log_string('fetched sensorpressureoutside from adafruit.io: {}'.format(sensor_pressure_outside))

            sensor_humidity_outside = self.aio_sensors.receive('sensorhumidityoutside')
            sensor_humidity_outside = float(sensor_humidity_outside.value)

            log_string('fetched sensorhumidityoutside from adafruit.io: {}'.format(sensor_humidity_outside))

            blink('blue')

            self.data['currently']['sensor_temp_inside'] = sensor_temp_inside
            self.data['currently']['sensor_pressure_inside'] = sensor_pressure_inside
            self.data['currently']['sensor_humidity_inside'] = sensor_humidity_inside

            log_string('added sensor data to temporary json data: '
                       'temp. inside:{} - humidity inside: {} - pressure inside: {}'.format(
                            sensor_temp_inside,
                            sensor_humidity_inside,
                            sensor_pressure_inside
                        ))

            self.data['currently']['sensor_temp_outside'] = sensor_temp_outside
            self.data['currently']['sensor_pressure_outside'] = sensor_pressure_outside
            self.data['currently']['sensor_humidity_outside'] = sensor_humidity_outside

            log_string('added sensor data to temporary json data: '
                       'temp. outside:{} - humidity outside: {} - pressure outside: {}'.format(
                            sensor_temp_outside,
                            sensor_humidity_outside,
                            sensor_pressure_outside
                        ))

            with open('/home/pi/WeatherPi/logs/latest_weather.json', 'w') as outputfile:
                json.dump(self.data, outputfile, indent=2, sort_keys=True)

            with open('/home/pi/WeatherPi/logs/current_weather.json', 'w') as outputfile:
                json.dump(self.data['currently'], outputfile, indent=2, sort_keys=True)

            log_string('json data saved to temporary file')

            os.system('cp /home/pi/WeatherPi/logs/latest_weather.json /var/www/html')
            os.system('cp /home/pi/WeatherPi/logs/current_weather.json /var/www/html')

            log_string('json data copied to /var/www/html')

            blink('white')

        except StandardError:

            log_string('ConnectionError - fallback to cached Data')

if __name__ == '__main__':
    Update().update_json()

<|endoftext|>


<commit_before># Copyright (c) 2013, Albert Zeyer, www.az2000.de
# All rights reserved.
# Code under 2-clause BSD licence.

import dis
import types

def _modified_abs_jumps(codestr, start, end, jumprel):
	codestr = bytearray(codestr)
	i = start
	while i < end:
		op = codestr[i]
		i += 1

		if op >= dis.HAVE_ARGUMENT:
			b1 = codestr[i]
			b2 = codestr[i+1]
			num = b2 * 256 + b1
			del b1,b2
			i += 2
		else:
			num = 0

		if op in dis.hasjabs:
			assert op >= dis.HAVE_ARGUMENT
			num += jumprel
			codestr[i-2] = chr(num & 255)
			codestr[i-1] = chr(num >> 8)

	return str(codestr)

def _codestr_without_final_return(codestr):
	assert len(codestr) >= 4
	assert codestr[-4] == dis.opmap["LOAD_CONST"]
	assert codestr[-1] == dis.opmap["RETURN_VALUE"]
	return codestr[:-4]

def _prefix_codestr(codestr1, codestr2):
	# see dis.findlinestarts() about co_firstlineno and co_lnotab
	codestr = codestr1 + codestr2
	codestr = _modified_abs_jumps(codestr, start=len(codestr1), end=len(codestr), jumprel=len(codestr1))
	return codestr

def _modified_code(c, **kwargs):
	CodeArgs = [
		"argcount", "nlocals", "stacksize", "flags", "code",
		"consts", "names", "varnames", "filename", "name",
		"firstlineno", "lnotab", "freevars", "cellvars"]
	c_dict = dict([(arg, getattr(c, "co_" + arg)) for arg in CodeArgs])

	for key,value in kwargs.items():
		assert key in c_dict
		c_dict[key] = value

	c = types.CodeType(*[c_dict[arg] for arg in CodeArgs])
	return c

def _find_setup_blocks(codestr, start, end):
	"Yields (op, absolute target instraddr, loop-type)"
	i = start
	SETUPS = [dis.opmap[opname] for opname in ["SETUP_LOOP", "SETUP_EXCEPT", "SETUP_FINALLY"]]
	POP_BLOCK = dis.opmap["POP_BLOCK"]
	FOR_ITER = dis.opmap["FOR_ITER"]
	blockstack = []
	while i < end:
		op = ord(codestr[i])
		i += 1

		if op >= dis.HAVE_ARGUMENT:
			b1 = ord(codestr[i])
			b2 = ord(codestr[i+1])
			num = b2 * 256 + b1
			del b1,b2
			i += 2
		else:
			num = 0

		if op in SETUPS:
			assert op >= dis.HAVE_ARGUMENT
			blockstack += [[op, i + num, None]]

		elif op == FOR_ITER:
			assert len(blockstack) > 0
			blockstack[-1][2] = op

		elif op == POP_BLOCK:
			assert len(blockstack) > 0
			blockstack.pop(len(blockstack) - 1)

	return blockstack

def restart_func(func, instraddr, localdict):
	"""
	Returns a new modified version of `func` which jumps right to instraddr
	with the localdict in place.

	Note that the way this currently works is limited because it uses
	only standard Python functions and objects. Only while-loops are supported.

	For-loops are not supported and are not possible this way.
	Except-blocks and with-blocks are not tested and will probably crash.
	"""

	# Another possibility to do this:
	# We need ctypes. Then we just save the full stack and the current op.
	# We can just load the full stack via LOAD_CONST.
	# This again has some problems such as that we don't want to resume
	# right at the op (because that might be the one raising an exception).
	# And if you want to resume somewhere else, you again need to manually
	# recalculate the stack so that it stays same.

	# And yet another:
	# We could also return a modified version of the func which automatically
	# replaces all for-loops with while-loops and store the iterator object
	# in a temporary local variable. However, still left is the problem that
	# many iterator objects (e.g. listiterator) are not pickable, so
	# serializing doesn't work. This again could be hacked via ctypes.

	preload_code = ""
	code_consts = func.func_code.co_consts
	LOAD_CONST = chr(dis.opmap["LOAD_CONST"])
	STORE_FAST = chr(dis.opmap["STORE_FAST"])
	for key,value in localdict.items():
		co_const_idx = len(code_consts)
		code_consts += (value,)
		preload_code += LOAD_CONST + chr(co_const_idx & 255) + chr(co_const_idx >> 8)
		varidx = func.func_code.co_varnames.index(key)
		preload_code += STORE_FAST + chr(varidx & 255) + chr(varidx >> 8)

	setup_blocks = _find_setup_blocks(func.func_code.co_code, start=0, end=instraddr)
	preload_code_len = len(localdict) * 6 + len(setup_blocks) * 3 + 3
	for op,targetaddr,looptype in setup_blocks:
		# Note on the loop-type:
		# Supporting for-loops is really complicated! We need to examine the stack of
		# the frame to get the iterator object. This cannot be done with the
		# normal Python APIs - we need ctypes to get raw access to PyFrameObject.
		# Then, even more complicated is to get the right stack address. You
		# have to go back from the opaddr where you are to the last FOR_ITER and count
		# the stack modifications.
		# Then, if you raise an exception and catch it outside, you already have lost
		# the stack and thus the iterator object - so this is not an option.
		# You need to do this while it is still active - e.g. from within an
		# exception trace function.
		assert looptype is None, "only while-loops supported at the moment"
		targetaddr += preload_code_len
		reladdr = targetaddr - (len(preload_code) + 3)
		preload_code += chr(op) + chr(reladdr & 255) + chr(reladdr >> 8)

	instraddr += preload_code_len
	preload_code += chr(dis.opmap["JUMP_ABSOLUTE"])
	preload_code += chr(instraddr & 255) + chr(instraddr >> 8)

	# Just a check. LoadConst+StoreFast, then .. and then JumpAbs.
	assert preload_code_len == len(preload_code)

	codestr = _prefix_codestr(preload_code, func.func_code.co_code)

	lnotab = func.func_code.co_lnotab
	lnotab_moverel = len(preload_code)
	while lnotab_moverel > 0:
		lnotab = chr(lnotab_moverel & 255) + chr(0) + lnotab
		lnotab_moverel -= lnotab_moverel & 255

	new_code = _modified_code(
		func.func_code,
		consts=code_consts,
		code=codestr,
		lnotab=lnotab,
		argcount=0
	)
	new_func = types.FunctionType(
		new_code,
		func.func_globals,
		func.func_name,
		func.func_defaults,
		func.func_closure,
	)
	return new_func

def simplify_loops(func):
	"""
	Returns a new modified version of `func` which behaves exactly the same but
	which has all for-loops replaced with while-loops. This makes it compatible
	for `restart_func`.
	"""

	codestr = list(map(ord, func.func_code.co_code))
	opaddrmap = dict(zip(range(len(codestr)), range(len(codestr))))

	# TODO: search for FOR_ITER, etc...

	# TODO: fix up lnotab.
	lnotab = ""

	# Fix up the absolute jumps.
	i = 0
	while i < len(codestr):
		op = codestr[i]
		i += 1

		if op >= dis.HAVE_ARGUMENT:
			b1 = codestr[i]
			b2 = codestr[i+1]
			num = b2 * 256 + b1
			del b1,b2
			i += 2
		else:
			num = 0

		if op in dis.hasjabs:
			assert op >= dis.HAVE_ARGUMENT
			num = opaddrmap[num]
			codestr[i-2] = chr(num & 255)
			codestr[i-1] = chr(num >> 8)

	new_code = _modified_code(
		func.func_code,
		code="".join(map(chr, codestr)),
		lnotab=lnotab,
	)
	new_func = types.FunctionType(
		new_code,
		func.func_globals,
		func.func_name,
		func.func_defaults,
		func.func_closure,
	)
	return new_func
<commit_msg>replace_code wip<commit_after># Copyright (c) 2013, Albert Zeyer, www.az2000.de
# All rights reserved.
# Code under 2-clause BSD licence.

import dis
import types

def _modified_abs_jumps(codestr, start, end, jumprel):
	codestr = bytearray(codestr)
	i = start
	while i < end:
		op = codestr[i]
		i += 1

		if op >= dis.HAVE_ARGUMENT:
			b1 = codestr[i]
			b2 = codestr[i+1]
			num = b2 * 256 + b1
			del b1,b2
			i += 2
		else:
			num = 0

		if op in dis.hasjabs:
			assert op >= dis.HAVE_ARGUMENT
			num += jumprel
			codestr[i-2] = chr(num & 255)
			codestr[i-1] = chr(num >> 8)

	return str(codestr)

def _codestr_without_final_return(codestr):
	assert len(codestr) >= 4
	assert codestr[-4] == dis.opmap["LOAD_CONST"]
	assert codestr[-1] == dis.opmap["RETURN_VALUE"]
	return codestr[:-4]

def _prefix_codestr(codestr1, codestr2):
	# see dis.findlinestarts() about co_firstlineno and co_lnotab
	codestr = codestr1 + codestr2
	codestr = _modified_abs_jumps(codestr, start=len(codestr1), end=len(codestr), jumprel=len(codestr1))
	return codestr

def _modified_code(c, **kwargs):
	CodeArgs = [
		"argcount", "nlocals", "stacksize", "flags", "code",
		"consts", "names", "varnames", "filename", "name",
		"firstlineno", "lnotab", "freevars", "cellvars"]
	c_dict = dict([(arg, getattr(c, "co_" + arg)) for arg in CodeArgs])

	for key,value in kwargs.items():
		assert key in c_dict
		c_dict[key] = value

	c = types.CodeType(*[c_dict[arg] for arg in CodeArgs])
	return c

def _find_setup_blocks(codestr, start, end):
	"Yields (op, absolute target instraddr, loop-type)"
	i = start
	SETUPS = [dis.opmap[opname] for opname in ["SETUP_LOOP", "SETUP_EXCEPT", "SETUP_FINALLY"]]
	POP_BLOCK = dis.opmap["POP_BLOCK"]
	FOR_ITER = dis.opmap["FOR_ITER"]
	blockstack = []
	while i < end:
		op = ord(codestr[i])
		i += 1

		if op >= dis.HAVE_ARGUMENT:
			b1 = ord(codestr[i])
			b2 = ord(codestr[i+1])
			num = b2 * 256 + b1
			del b1,b2
			i += 2
		else:
			num = 0

		if op in SETUPS:
			assert op >= dis.HAVE_ARGUMENT
			blockstack += [[op, i + num, None]]

		elif op == FOR_ITER:
			assert len(blockstack) > 0
			blockstack[-1][2] = op

		elif op == POP_BLOCK:
			assert len(blockstack) > 0
			blockstack.pop(len(blockstack) - 1)

	return blockstack

def replace_code(codeobj, instaddr, removelen, addcodestr):
	assert isinstance(codeobj, types.CodeType)
	lnotab = codeobj.co_lnotab
	assert len(lnotab) % 2 == 0

	# Search right place in lnotab.
	lnotab_instaddr = 0
	lnotab_idx = 0
	lnotab_len = len(lnotab)
	while lnotab_idx < lnotab_len:
		if lnotab_instaddr >= instaddr: break
		addrincr, lineincr = map(ord, lnotab[lnotab_idx:lnotab_idx+2])
		lnotab_instaddr += addrincr
		lnotab_idx += 2
	assert lnotab_instaddr >= instaddr, "instaddr %i not in lnotab" % instaddr

	# If we skipped it, insert a dummy entry to lnotab.
	if lnotab_instaddr > instaddr:
		# Insert. addrincr, lineincr are from the last entry.
		lnotab = \
			lnotab[:lnotab_idx-2] + \
			chr(addrincr - (lnotab_instaddr - instaddr)) + chr(0) + \
			chr(lnotab_instaddr - instaddr) + chr(lineincr) + \
			lnotab[lnotab_idx:]
		lnotab_idx -= 2
		lnotab_instaddr = instaddr
	del addrincr, lineincr
	assert lnotab_instaddr == instaddr
	# And lnotab_idx is right where the upcoming lnotab-data starts.

	# Check whether instaddr is sane.
	codestr = codeobj.co_code
	codeidx = 0
	codelen = len(codestr)
	while codeidx < codelen:
		if codeidx >= instaddr: break
		op = ord(codestr[codeidx])
		codeidx += 1
		if op >= dis.HAVE_ARGUMENT: codeidx += 2
	assert codeidx == instaddr, "instaddr %i doesn't align in code" % instaddr

	# Check whether removelen is sane.
	while codeidx < codelen:
		if codeidx >= instaddr + removelen: break
		op = ord(codestr[codeidx])
		codeidx += 1
		if op >= dis.HAVE_ARGUMENT: codeidx += 2
	assert codeidx == instaddr + removelen, "removelen %i doesn't align in code" % removelen

	# Update lnotab for removed code.
	codelendiff = -removelen
	while codelendiff < 0:
		pass

	# Update lnotab for new code.
	codelendiff = len(addcodestr)
	while codelendiff > 0:
		lnotab = \
			lnotab[:lnotab_idx] + \
			chr(codelendiff & 255) + chr(0) + \
			lnotab[lnotab_idx:]
		codelendiff -= codelendiff & 255

	# Check whether addcodestr is sane.
	codeidx = 0
	codelen = len(addcodestr)
	while codeidx < codelen:
		op = ord(codestr[codeidx])
		codeidx += 1
		if op >= dis.HAVE_ARGUMENT: codeidx += 2
	assert codeidx == codelen, "addcodestr is not sane"

	# Update codestr.
	codestr = \
		codestr[:instaddr] + \
		addcodestr + \
		codestr[instaddr+removelen:]

	# Return new code object.
	new_code = _modified_code(
		codeobj,
		code=codestr,
		lnotab=lnotab,
	)
	return new_code

def restart_func(func, instraddr, localdict):
	"""
	Returns a new modified version of `func` which jumps right to instraddr
	with the localdict in place.

	Note that the way this currently works is limited because it uses
	only standard Python functions and objects. Only while-loops are supported.

	For-loops are not supported and are not possible this way.
	Except-blocks and with-blocks are not tested and will probably crash.
	"""

	# Another possibility to do this:
	# We need ctypes. Then we just save the full stack and the current op.
	# We can just load the full stack via LOAD_CONST.
	# This again has some problems such as that we don't want to resume
	# right at the op (because that might be the one raising an exception).
	# And if you want to resume somewhere else, you again need to manually
	# recalculate the stack so that it stays same.

	# And yet another:
	# We could also return a modified version of the func which automatically
	# replaces all for-loops with while-loops and store the iterator object
	# in a temporary local variable. However, still left is the problem that
	# many iterator objects (e.g. listiterator) are not pickable, so
	# serializing doesn't work. This again could be hacked via ctypes.

	preload_code = ""
	code_consts = func.func_code.co_consts
	LOAD_CONST = chr(dis.opmap["LOAD_CONST"])
	STORE_FAST = chr(dis.opmap["STORE_FAST"])
	for key,value in localdict.items():
		co_const_idx = len(code_consts)
		code_consts += (value,)
		preload_code += LOAD_CONST + chr(co_const_idx & 255) + chr(co_const_idx >> 8)
		varidx = func.func_code.co_varnames.index(key)
		preload_code += STORE_FAST + chr(varidx & 255) + chr(varidx >> 8)

	setup_blocks = _find_setup_blocks(func.func_code.co_code, start=0, end=instraddr)
	preload_code_len = len(localdict) * 6 + len(setup_blocks) * 3 + 3
	for op,targetaddr,looptype in setup_blocks:
		# Note on the loop-type:
		# Supporting for-loops is really complicated! We need to examine the stack of
		# the frame to get the iterator object. This cannot be done with the
		# normal Python APIs - we need ctypes to get raw access to PyFrameObject.
		# Then, even more complicated is to get the right stack address. You
		# have to go back from the opaddr where you are to the last FOR_ITER and count
		# the stack modifications.
		# Then, if you raise an exception and catch it outside, you already have lost
		# the stack and thus the iterator object - so this is not an option.
		# You need to do this while it is still active - e.g. from within an
		# exception trace function.
		assert looptype is None, "only while-loops supported at the moment"
		targetaddr += preload_code_len
		reladdr = targetaddr - (len(preload_code) + 3)
		preload_code += chr(op) + chr(reladdr & 255) + chr(reladdr >> 8)

	instraddr += preload_code_len
	preload_code += chr(dis.opmap["JUMP_ABSOLUTE"])
	preload_code += chr(instraddr & 255) + chr(instraddr >> 8)

	# Just a check. LoadConst+StoreFast, then .. and then JumpAbs.
	assert preload_code_len == len(preload_code)

	codestr = _prefix_codestr(preload_code, func.func_code.co_code)

	lnotab = func.func_code.co_lnotab
	lnotab_moverel = len(preload_code)
	while lnotab_moverel > 0:
		lnotab = chr(lnotab_moverel & 255) + chr(0) + lnotab
		lnotab_moverel -= lnotab_moverel & 255

	new_code = _modified_code(
		func.func_code,
		consts=code_consts,
		code=codestr,
		lnotab=lnotab,
		argcount=0
	)
	new_func = types.FunctionType(
		new_code,
		func.func_globals,
		func.func_name,
		func.func_defaults,
		func.func_closure,
	)
	return new_func

def simplify_loops(func):
	"""
	Returns a new modified version of `func` which behaves exactly the same but
	which has all for-loops replaced with while-loops. This makes it compatible
	for `restart_func`.
	"""

	codestr = list(map(ord, func.func_code.co_code))
	opaddrmap = dict(zip(range(len(codestr)), range(len(codestr))))

	# TODO: search for FOR_ITER, etc...

	# TODO: fix up lnotab.
	lnotab = ""

	# Fix up the absolute jumps.
	i = 0
	while i < len(codestr):
		op = codestr[i]
		i += 1

		if op >= dis.HAVE_ARGUMENT:
			b1 = codestr[i]
			b2 = codestr[i+1]
			num = b2 * 256 + b1
			del b1,b2
			i += 2
		else:
			num = 0

		if op in dis.hasjabs:
			assert op >= dis.HAVE_ARGUMENT
			num = opaddrmap[num]
			codestr[i-2] = chr(num & 255)
			codestr[i-1] = chr(num >> 8)

	new_code = _modified_code(
		func.func_code,
		code="".join(map(chr, codestr)),
		lnotab=lnotab,
	)
	new_func = types.FunctionType(
		new_code,
		func.func_globals,
		func.func_name,
		func.func_defaults,
		func.func_closure,
	)
	return new_func
<|endoftext|>