"""
    Agilicus API

    Agilicus is API-first. Modern software is controlled by other software, is open, is available for you to use the way you want, securely, simply.  The OpenAPI Specification in YAML format is available on [www](https://www.agilicus.com/www/api/agilicus-openapi.yaml) for importing to other tools.  A rendered, online viewable and usable version of this specification is available at [api](https://www.agilicus.com/api). You may try the API inline directly in the web page. To do so, first obtain an Authentication Token (the simplest way is to install the Python SDK, and then run `agilicus-cli --issuer https://MYISSUER get-token`). You will need an org-id for most calls (and can obtain from `agilicus-cli --issuer https://MYISSUER list-orgs`). The `MYISSUER` will typically be `auth.MYDOMAIN`, and you will see it as you sign-in to the administrative UI.  This API releases on Bearer-Token authentication. To obtain a valid bearer token you will need to Authenticate to an Issuer with OpenID Connect (a superset of OAUTH2).  Your \"issuer\" will look like https://auth.MYDOMAIN. For example, when you signed-up, if you said \"use my own domain name\" and assigned a CNAME of cloud.example.com, then your issuer would be https://auth.cloud.example.com.  If you selected \"use an Agilicus supplied domain name\", your issuer would look like https://auth.myorg.agilicus.cloud.  For test purposes you can use our [Python SDK](https://pypi.org/project/agilicus/) and run `agilicus-cli --issuer https://auth.MYDOMAIN get-token`.  This API may be used in any language runtime that supports OpenAPI 3.0, or, you may use our [Python SDK](https://pypi.org/project/agilicus/), our [Typescript SDK](https://www.npmjs.com/package/@agilicus/angular), or our [Golang SDK](https://git.agilicus.com/pub/sdk-go).  100% of the activities in our system our API-driven, from our web-admin, through our progressive web applications, to all internals: there is nothing that is not accessible.  For more information, see [developer resources](https://www.agilicus.com/developer).   # noqa: E501

    The version of the OpenAPI document: 2023.10.24
    Contact: dev@agilicus.com
    Generated by: https://openapi-generator.tech
"""


import re  # noqa: F401
import sys  # noqa: F401

from agilicus_api.model_utils import (  # noqa: F401
    ApiTypeError,
    ModelComposed,
    ModelNormal,
    ModelSimple,
    cached_property,
    change_keys_js_to_python,
    convert_js_args_to_python_args,
    date,
    datetime,
    file_type,
    none_type,
    validate_get_composed_info,
)
from ..model_utils import OpenApiModel
from agilicus_api.exceptions import ApiAttributeError


def lazy_import():
    from agilicus_api.model.feature_flag import FeatureFlag
    from agilicus_api.model.k8s_slug import K8sSlug
    from agilicus_api.model.organisation_capabilities import OrganisationCapabilities
    from agilicus_api.model.organisation_owner_config import OrganisationOwnerConfig
    from agilicus_api.model.organisation_state_selector import OrganisationStateSelector
    from agilicus_api.model.organisation_status import OrganisationStatus
    globals()['FeatureFlag'] = FeatureFlag
    globals()['K8sSlug'] = K8sSlug
    globals()['OrganisationCapabilities'] = OrganisationCapabilities
    globals()['OrganisationOwnerConfig'] = OrganisationOwnerConfig
    globals()['OrganisationStateSelector'] = OrganisationStateSelector
    globals()['OrganisationStatus'] = OrganisationStatus


class Organisation(ModelNormal):
    """NOTE: This class is auto generated by OpenAPI Generator.
    Ref: https://openapi-generator.tech

    Do not edit the class manually.

    Attributes:
      allowed_values (dict): The key is the tuple path to the attribute
          and the for var_name this is (var_name,). The value is a dict
          with a capitalized key describing the allowed value and an allowed
          value. These dicts store the allowed enum values.
      attribute_map (dict): The key is attribute name
          and the value is json key in definition.
      discriminator_value_class_map (dict): A dict to go from the discriminator
          variable value to the discriminator class name.
      validations (dict): The key is the tuple path to the attribute
          and the for var_name this is (var_name,). The value is a dict
          that stores validations for max_length, min_length, max_items,
          min_items, exclusive_maximum, inclusive_maximum, exclusive_minimum,
          inclusive_minimum, and regex.
      additional_properties_type (tuple): A tuple of classes accepted
          as additional properties values.
    """

    allowed_values = {
    }

    validations = {
        ('external_id',): {
            'max_length': 100,
        },
        ('organisation',): {
            'max_length': 100,
        },
        ('issuer',): {
            'max_length': 100,
        },
        ('subdomain',): {
            'max_length': 100,
        },
        ('contact_email',): {
            'max_length': 100,
        },
        ('trust_on_first_use_duration',): {
            'inclusive_minimum': 0,
        },
        ('shard',): {
            'max_length': 50,
        },
        ('cluster',): {
            'max_length': 32,
        },
        ('product_label_override',): {
            'max_length': 32,
            'regex': {
                'pattern': r'^[a-zA-Z0-9-_.:]+$',  # noqa: E501
            },
        },
    }

    @property
    def id(self):
       return self.get("id")

    @id.setter
    def id(self, new_value):
       self.id = new_value

    @property
    def all_users_group_id(self):
       return self.get("all_users_group_id")

    @all_users_group_id.setter
    def all_users_group_id(self, new_value):
       self.all_users_group_id = new_value

    @property
    def all_users_all_suborgs_group_id(self):
       return self.get("all_users_all_suborgs_group_id")

    @all_users_all_suborgs_group_id.setter
    def all_users_all_suborgs_group_id(self, new_value):
       self.all_users_all_suborgs_group_id = new_value

    @property
    def all_users_direct_suborgs_group_id(self):
       return self.get("all_users_direct_suborgs_group_id")

    @all_users_direct_suborgs_group_id.setter
    def all_users_direct_suborgs_group_id(self, new_value):
       self.all_users_direct_suborgs_group_id = new_value

    @property
    def auto_created_users_group_id(self):
       return self.get("auto_created_users_group_id")

    @auto_created_users_group_id.setter
    def auto_created_users_group_id(self, new_value):
       self.auto_created_users_group_id = new_value

    @property
    def external_id(self):
       return self.get("external_id")

    @external_id.setter
    def external_id(self, new_value):
       self.external_id = new_value

    @property
    def organisation(self):
       return self.get("organisation")

    @organisation.setter
    def organisation(self, new_value):
       self.organisation = new_value

    @property
    def issuer(self):
       return self.get("issuer")

    @issuer.setter
    def issuer(self, new_value):
       self.issuer = new_value

    @property
    def issuer_id(self):
       return self.get("issuer_id")

    @issuer_id.setter
    def issuer_id(self, new_value):
       self.issuer_id = new_value

    @property
    def subdomain(self):
       return self.get("subdomain")

    @subdomain.setter
    def subdomain(self, new_value):
       self.subdomain = new_value

    @property
    def name_slug(self):
       return self.get("name_slug")

    @name_slug.setter
    def name_slug(self, new_value):
       self.name_slug = new_value

    @property
    def created(self):
       return self.get("created")

    @created.setter
    def created(self, new_value):
       self.created = new_value

    @property
    def updated(self):
       return self.get("updated")

    @updated.setter
    def updated(self, new_value):
       self.updated = new_value

    @property
    def contact_id(self):
       return self.get("contact_id")

    @contact_id.setter
    def contact_id(self, new_value):
       self.contact_id = new_value

    @property
    def contact_email(self):
       return self.get("contact_email")

    @contact_email.setter
    def contact_email(self, new_value):
       self.contact_email = new_value

    @property
    def parent_id(self):
       return self.get("parent_id")

    @parent_id.setter
    def parent_id(self, new_value):
       self.parent_id = new_value

    @property
    def root_org_id(self):
       return self.get("root_org_id")

    @root_org_id.setter
    def root_org_id(self, new_value):
       self.root_org_id = new_value

    @property
    def auto_create(self):
       return self.get("auto_create")

    @auto_create.setter
    def auto_create(self, new_value):
       self.auto_create = new_value

    @property
    def trust_on_first_use_duration(self):
       return self.get("trust_on_first_use_duration")

    @trust_on_first_use_duration.setter
    def trust_on_first_use_duration(self, new_value):
       self.trust_on_first_use_duration = new_value

    @property
    def feature_flags(self):
       return self.get("feature_flags")

    @feature_flags.setter
    def feature_flags(self, new_value):
       self.feature_flags = new_value

    @property
    def admin_state(self):
       return self.get("admin_state")

    @admin_state.setter
    def admin_state(self, new_value):
       self.admin_state = new_value

    @property
    def status(self):
       return self.get("status")

    @status.setter
    def status(self, new_value):
       self.status = new_value

    @property
    def billing_account_id(self):
       return self.get("billing_account_id")

    @billing_account_id.setter
    def billing_account_id(self, new_value):
       self.billing_account_id = new_value

    @property
    def billing_subscription_id(self):
       return self.get("billing_subscription_id")

    @billing_subscription_id.setter
    def billing_subscription_id(self, new_value):
       self.billing_subscription_id = new_value

    @property
    def shard(self):
       return self.get("shard")

    @shard.setter
    def shard(self, new_value):
       self.shard = new_value

    @property
    def cluster(self):
       return self.get("cluster")

    @cluster.setter
    def cluster(self, new_value):
       self.cluster = new_value

    @property
    def configured_capabilities(self):
       return self.get("configured_capabilities")

    @configured_capabilities.setter
    def configured_capabilities(self, new_value):
       self.configured_capabilities = new_value

    @property
    def owner_config(self):
       return self.get("owner_config")

    @owner_config.setter
    def owner_config(self, new_value):
       self.owner_config = new_value

    @property
    def product_label_override(self):
       return self.get("product_label_override")

    @product_label_override.setter
    def product_label_override(self, new_value):
       self.product_label_override = new_value

    @cached_property
    def additional_properties_type():
        """
        This must be a method because a model may have properties that are
        of type self, this must run after the class is loaded
        """
        lazy_import()
        return (bool, date, datetime, dict, float, int, list, str, none_type,)  # noqa: E501

    _nullable = False

    @cached_property
    def openapi_types():
        """
        This must be a method because a model may have properties that are
        of type self, this must run after the class is loaded

        Returns
            openapi_types (dict): The key is attribute name
                and the value is attribute type.
        """
        lazy_import()
        return {
            'id': (str,),  # noqa: E501
            'all_users_group_id': (str,),  # noqa: E501
            'all_users_all_suborgs_group_id': (str,),  # noqa: E501
            'all_users_direct_suborgs_group_id': (str,),  # noqa: E501
            'auto_created_users_group_id': (str,),  # noqa: E501
            'external_id': (str,),  # noqa: E501
            'organisation': (str,),  # noqa: E501
            'issuer': (str,),  # noqa: E501
            'issuer_id': (str,),  # noqa: E501
            'subdomain': (str,),  # noqa: E501
            'name_slug': (K8sSlug,),  # noqa: E501
            'created': (datetime,),  # noqa: E501
            'updated': (datetime,),  # noqa: E501
            'contact_id': (str,),  # noqa: E501
            'contact_email': (str,),  # noqa: E501
            'parent_id': (str,),  # noqa: E501
            'root_org_id': (str,),  # noqa: E501
            'auto_create': (bool,),  # noqa: E501
            'trust_on_first_use_duration': (int,),  # noqa: E501
            'feature_flags': ([FeatureFlag],),  # noqa: E501
            'admin_state': (OrganisationStateSelector,),  # noqa: E501
            'status': (OrganisationStatus,),  # noqa: E501
            'billing_account_id': (str,),  # noqa: E501
            'billing_subscription_id': (str,),  # noqa: E501
            'shard': (str,),  # noqa: E501
            'cluster': (str,),  # noqa: E501
            'configured_capabilities': (OrganisationCapabilities,),  # noqa: E501
            'owner_config': (OrganisationOwnerConfig,),  # noqa: E501
            'product_label_override': (str,),  # noqa: E501
        }

    @cached_property
    def discriminator():
        return None



    attribute_map = {
        'id': 'id',  # noqa: E501
        'all_users_group_id': 'all_users_group_id',  # noqa: E501
        'all_users_all_suborgs_group_id': 'all_users_all_suborgs_group_id',  # noqa: E501
        'all_users_direct_suborgs_group_id': 'all_users_direct_suborgs_group_id',  # noqa: E501
        'auto_created_users_group_id': 'auto_created_users_group_id',  # noqa: E501
        'external_id': 'external_id',  # noqa: E501
        'organisation': 'organisation',  # noqa: E501
        'issuer': 'issuer',  # noqa: E501
        'issuer_id': 'issuer_id',  # noqa: E501
        'subdomain': 'subdomain',  # noqa: E501
        'name_slug': 'name_slug',  # noqa: E501
        'created': 'created',  # noqa: E501
        'updated': 'updated',  # noqa: E501
        'contact_id': 'contact_id',  # noqa: E501
        'contact_email': 'contact_email',  # noqa: E501
        'parent_id': 'parent_id',  # noqa: E501
        'root_org_id': 'root_org_id',  # noqa: E501
        'auto_create': 'auto_create',  # noqa: E501
        'trust_on_first_use_duration': 'trust_on_first_use_duration',  # noqa: E501
        'feature_flags': 'feature_flags',  # noqa: E501
        'admin_state': 'admin_state',  # noqa: E501
        'status': 'status',  # noqa: E501
        'billing_account_id': 'billing_account_id',  # noqa: E501
        'billing_subscription_id': 'billing_subscription_id',  # noqa: E501
        'shard': 'shard',  # noqa: E501
        'cluster': 'cluster',  # noqa: E501
        'configured_capabilities': 'configured_capabilities',  # noqa: E501
        'owner_config': 'owner_config',  # noqa: E501
        'product_label_override': 'product_label_override',  # noqa: E501
    }

    read_only_vars = {
        'id',  # noqa: E501
        'created',  # noqa: E501
        'updated',  # noqa: E501
        'contact_email',  # noqa: E501
    }

    _composed_schemas = {}

    @classmethod
    @convert_js_args_to_python_args
    def _from_openapi_data(cls, *args, **kwargs):  # noqa: E501
        """Organisation - a model defined in OpenAPI

        Keyword Args:
            _check_type (bool): if True, values for parameters in openapi_types
                                will be type checked and a TypeError will be
                                raised if the wrong type is input.
                                Defaults to True
            _path_to_item (tuple/list): This is a list of keys or values to
                                drill down to the model in received_data
                                when deserializing a response
            _spec_property_naming (bool): True if the variable names in the input data
                                are serialized names, as specified in the OpenAPI document.
                                False if the variable names in the input data
                                are pythonic names, e.g. snake case (default)
            _configuration (Configuration): the instance to use when
                                deserializing a file_type parameter.
                                If passed, type conversion is attempted
                                If omitted no type conversion is done.
            _visited_composed_classes (tuple): This stores a tuple of
                                classes that we have traveled through so that
                                if we see that class again we will not use its
                                discriminator again.
                                When traveling through a discriminator, the
                                composed schema that is
                                is traveled through is added to this set.
                                For example if Animal has a discriminator
                                petType and we pass in "Dog", and the class Dog
                                allOf includes Animal, we move through Animal
                                once using the discriminator, and pick Dog.
                                Then in Dog, we will make an instance of the
                                Animal class but this time we won't travel
                                through its discriminator because we passed in
                                _visited_composed_classes = (Animal,)
            id (str): Unique identifier. [optional]  # noqa: E501
            all_users_group_id (str): group id of group containing this organisations all users. [optional]  # noqa: E501
            all_users_all_suborgs_group_id (str): group id of group containing this organisations all users including all sub organisations. [optional]  # noqa: E501
            all_users_direct_suborgs_group_id (str): group id of group containing this organisations all users including only direct sub organisations. [optional]  # noqa: E501
            auto_created_users_group_id (str): group id of group containing users automatically created when they logged in. [optional]  # noqa: E501
            external_id (str): External unique identifier. [optional]  # noqa: E501
            organisation (str): organisation name. [optional]  # noqa: E501
            issuer (str): connect id issuer. [optional]  # noqa: E501
            issuer_id (str): Unique identifier. [optional]  # noqa: E501
            subdomain (str): Organisations subdomain. Note this must be unique accross all organisations. [optional]  # noqa: E501
            name_slug (K8sSlug): [optional]  # noqa: E501
            created (datetime): Creation time. [optional]  # noqa: E501
            updated (datetime): Update time. [optional]  # noqa: E501
            contact_id (str): GUID of the organisation admin. [optional]  # noqa: E501
            contact_email (str): The email address of the contact.. [optional]  # noqa: E501
            parent_id (str): parent organisation id. [optional]  # noqa: E501
            root_org_id (str): The id of the organisation at the root of this organisation hierarchy. For example, if A is the parent of B, and B is the parent of C, then A would be the root organisation of A, B and C. Note that this field will be ignored if changed. . [optional]  # noqa: E501
            auto_create (bool): Auto-creates a user. [optional] if omitted the server will use the default value of False  # noqa: E501
            trust_on_first_use_duration (int): The time window in seconds which represents the period of time for which a new user is eligible for trust on first use enrollment. The duration will be applied from the user's created date, or if the user's enrollment period was reset by an administrator. . [optional] if omitted the server will use the default value of 86400  # noqa: E501
            feature_flags ([FeatureFlag]): A list of features to enable or disable. This is mostly for advanced use. No guarantees exist that a given feature will always exist by a given name, or that it will be configurable. . [optional]  # noqa: E501
            admin_state (OrganisationStateSelector): [optional]  # noqa: E501
            status (OrganisationStatus): [optional]  # noqa: E501
            billing_account_id (str): The billing account id. [optional]  # noqa: E501
            billing_subscription_id (str): The billing subscription id. [optional]  # noqa: E501
            shard (str): The shard to use on the agilicus platform. This provides logical seperation on the agilicus platform. This can be used to prevent access to applications between suborgs in the same organisation. . [optional]  # noqa: E501
            cluster (str): The agilicus cluster/region to host the platform on. This provides information to determine what physical location any services provided should run from. Consult the list of Regions for the possible values to set here. Changing this value will cause resources to move to the new cluster. Changing the setting will cause a few minutes of downtime while resources are moved. You will have to change the cname for your domain in order to attract traffic to the correct location. . [optional]  # noqa: E501
            configured_capabilities (OrganisationCapabilities): [optional]  # noqa: E501
            owner_config (OrganisationOwnerConfig): [optional]  # noqa: E501
            product_label_override (str): Override the default product label. . [optional]  # noqa: E501
        """

        _check_type = kwargs.pop('_check_type', True)
        _spec_property_naming = kwargs.pop('_spec_property_naming', False)
        _path_to_item = kwargs.pop('_path_to_item', ())
        _configuration = kwargs.pop('_configuration', None)
        _visited_composed_classes = kwargs.pop('_visited_composed_classes', ())

        self = super(OpenApiModel, cls).__new__(cls)

        if args:
            raise ApiTypeError(
                "Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
                    args,
                    self.__class__.__name__,
                ),
                path_to_item=_path_to_item,
                valid_classes=(self.__class__,),
            )

        self._data_store = {}
        self._check_type = _check_type
        self._spec_property_naming = _spec_property_naming
        self._path_to_item = _path_to_item
        self._configuration = _configuration
        self._visited_composed_classes = _visited_composed_classes + (self.__class__,)

        for var_name, var_value in kwargs.items():
            if var_name not in self.attribute_map and \
                        self._configuration is not None and \
                        self._configuration.discard_unknown_keys and \
                        self.additional_properties_type is None:
                # discard variable.
                continue
            setattr(self, var_name, var_value)
        return self

    def __python_set(val):
        return set(val)
 
    required_properties = __python_set([
        '_data_store',
        '_check_type',
        '_spec_property_naming',
        '_path_to_item',
        '_configuration',
        '_visited_composed_classes',
    ])

    @convert_js_args_to_python_args
    def __init__(self, *args, **kwargs):  # noqa: E501
        """Organisation - a model defined in OpenAPI

        Keyword Args:
            _check_type (bool): if True, values for parameters in openapi_types
                                will be type checked and a TypeError will be
                                raised if the wrong type is input.
                                Defaults to True
            _path_to_item (tuple/list): This is a list of keys or values to
                                drill down to the model in received_data
                                when deserializing a response
            _spec_property_naming (bool): True if the variable names in the input data
                                are serialized names, as specified in the OpenAPI document.
                                False if the variable names in the input data
                                are pythonic names, e.g. snake case (default)
            _configuration (Configuration): the instance to use when
                                deserializing a file_type parameter.
                                If passed, type conversion is attempted
                                If omitted no type conversion is done.
            _visited_composed_classes (tuple): This stores a tuple of
                                classes that we have traveled through so that
                                if we see that class again we will not use its
                                discriminator again.
                                When traveling through a discriminator, the
                                composed schema that is
                                is traveled through is added to this set.
                                For example if Animal has a discriminator
                                petType and we pass in "Dog", and the class Dog
                                allOf includes Animal, we move through Animal
                                once using the discriminator, and pick Dog.
                                Then in Dog, we will make an instance of the
                                Animal class but this time we won't travel
                                through its discriminator because we passed in
                                _visited_composed_classes = (Animal,)
            id (str): Unique identifier. [optional]  # noqa: E501
            all_users_group_id (str): group id of group containing this organisations all users. [optional]  # noqa: E501
            all_users_all_suborgs_group_id (str): group id of group containing this organisations all users including all sub organisations. [optional]  # noqa: E501
            all_users_direct_suborgs_group_id (str): group id of group containing this organisations all users including only direct sub organisations. [optional]  # noqa: E501
            auto_created_users_group_id (str): group id of group containing users automatically created when they logged in. [optional]  # noqa: E501
            external_id (str): External unique identifier. [optional]  # noqa: E501
            organisation (str): organisation name. [optional]  # noqa: E501
            issuer (str): connect id issuer. [optional]  # noqa: E501
            issuer_id (str): Unique identifier. [optional]  # noqa: E501
            subdomain (str): Organisations subdomain. Note this must be unique accross all organisations. [optional]  # noqa: E501
            name_slug (K8sSlug): [optional]  # noqa: E501
            created (datetime): Creation time. [optional]  # noqa: E501
            updated (datetime): Update time. [optional]  # noqa: E501
            contact_id (str): GUID of the organisation admin. [optional]  # noqa: E501
            contact_email (str): The email address of the contact.. [optional]  # noqa: E501
            parent_id (str): parent organisation id. [optional]  # noqa: E501
            root_org_id (str): The id of the organisation at the root of this organisation hierarchy. For example, if A is the parent of B, and B is the parent of C, then A would be the root organisation of A, B and C. Note that this field will be ignored if changed. . [optional]  # noqa: E501
            auto_create (bool): Auto-creates a user. [optional] if omitted the server will use the default value of False  # noqa: E501
            trust_on_first_use_duration (int): The time window in seconds which represents the period of time for which a new user is eligible for trust on first use enrollment. The duration will be applied from the user's created date, or if the user's enrollment period was reset by an administrator. . [optional] if omitted the server will use the default value of 86400  # noqa: E501
            feature_flags ([FeatureFlag]): A list of features to enable or disable. This is mostly for advanced use. No guarantees exist that a given feature will always exist by a given name, or that it will be configurable. . [optional]  # noqa: E501
            admin_state (OrganisationStateSelector): [optional]  # noqa: E501
            status (OrganisationStatus): [optional]  # noqa: E501
            billing_account_id (str): The billing account id. [optional]  # noqa: E501
            billing_subscription_id (str): The billing subscription id. [optional]  # noqa: E501
            shard (str): The shard to use on the agilicus platform. This provides logical seperation on the agilicus platform. This can be used to prevent access to applications between suborgs in the same organisation. . [optional]  # noqa: E501
            cluster (str): The agilicus cluster/region to host the platform on. This provides information to determine what physical location any services provided should run from. Consult the list of Regions for the possible values to set here. Changing this value will cause resources to move to the new cluster. Changing the setting will cause a few minutes of downtime while resources are moved. You will have to change the cname for your domain in order to attract traffic to the correct location. . [optional]  # noqa: E501
            configured_capabilities (OrganisationCapabilities): [optional]  # noqa: E501
            owner_config (OrganisationOwnerConfig): [optional]  # noqa: E501
            product_label_override (str): Override the default product label. . [optional]  # noqa: E501
        """

        _check_type = kwargs.pop('_check_type', True)
        _spec_property_naming = kwargs.pop('_spec_property_naming', False)
        _path_to_item = kwargs.pop('_path_to_item', ())
        _configuration = kwargs.pop('_configuration', None)
        _visited_composed_classes = kwargs.pop('_visited_composed_classes', ())

        if args:
            raise ApiTypeError(
                "Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
                    args,
                    self.__class__.__name__,
                ),
                path_to_item=_path_to_item,
                valid_classes=(self.__class__,),
            )

        self._data_store = {}
        self._check_type = _check_type
        self._spec_property_naming = _spec_property_naming
        self._path_to_item = _path_to_item
        self._configuration = _configuration
        self._visited_composed_classes = _visited_composed_classes + (self.__class__,)

        for var_name, var_value in kwargs.items():
            if var_name not in self.attribute_map and \
                        self._configuration is not None and \
                        self._configuration.discard_unknown_keys and \
                        self.additional_properties_type is None:
                # discard variable.
                continue
            setattr(self, var_name, var_value)
            if var_name in self.read_only_vars:
                raise ApiAttributeError(f"`{var_name}` is a read-only attribute. Use `from_openapi_data` to instantiate "
                                     f"class with read only attributes.")

