# Path: lepo/apidef/operation/openapi.py
# class OpenAPI3Operation(Operation):
#     parameter_class = OpenAPI3Parameter
#     body_parameter_class = OpenAPI3BodyParameter
# 
#     def _get_body_parameter(self):
#         for source in (
#             self.path.mapping.get('requestBody'),
#             self.data.get('requestBody'),
#         ):
#             if source:
#                 source = maybe_resolve(source, self.api.resolve_reference)
#                 body_parameter = self.body_parameter_class(data=source, operation=self, api=self.api)
#                 # TODO: Document x-lepo-body-name
#                 body_parameter.name = self.data.get('x-lepo-body-name', body_parameter.name)
#                 return body_parameter
# 
#     def get_parameter_dict(self):
#         parameter_dict = super().get_parameter_dict()
#         for parameter in parameter_dict.values():
#             if parameter.in_body:  # pragma: no cover
#                 raise ValueError('Regular parameter declared to be in body while parsing OpenAPI 3')
#         body_parameter = self._get_body_parameter()
#         if body_parameter:
#             parameter_dict[body_parameter.name] = body_parameter
#         return parameter_dict
# 
# Path: lepo/apidef/operation/swagger.py
# class Swagger2Operation(Operation):
#     parameter_class = Swagger2Parameter
# 
#     @cached_property
#     def consumes(self):
#         value = self._get_overridable('consumes', [])
#         if not isinstance(value, (list, tuple)):
#             raise TypeError(f'`consumes` must be a list, got {value!r}')  # pragma: no cover
#         return value
# 
#     @cached_property
#     def produces(self):
#         value = self._get_overridable('produces', [])
#         if not isinstance(value, (list, tuple)):
#             raise TypeError(f'`produces` must be a list, got {value!r}')  # pragma: no cover
#         return value
# 
# Path: lepo/apidef/path.py
# class Path:
#     def __init__(self, api, path, mapping):
#         """
#         :type api: lepo.apidef.APIDefinition
#         :type path: str
#         :type mapping: dict
#         """
#         self.api = api
#         self.path = path
#         self.mapping = mapping
#         self.regex = self._build_regex()
#         self.name = self._build_view_name()
# 
#     def get_view_class(self, router):
#         return type(f'{self.name.title()}View', (PathView,), {
#             'path': self,
#             'router': router,
#         })
# 
#     def _build_view_name(self):
#         path = re.sub(PATH_PLACEHOLDER_REGEX, r'\1', self.path)
#         name = re.sub(r'[^a-z0-9]+', '-', path, flags=re.I).strip('-').lower()
#         return name
# 
#     def _build_regex(self):
#         return re.sub(
#             PATH_PLACEHOLDER_REGEX,
#             lambda m: f'(?P<{m.group(1)}>[^/]+?)',
#             self.path,
#         ).lstrip('/') + '$'
# 
#     def get_operation(self, method):
#         operation_data = self.mapping.get(method.lower())
#         if not operation_data:
#             raise InvalidOperation(f'Path {self.path} does not support method {method.upper()}')
#         return self.api.operation_class(api=self.api, path=self, data=operation_data, method=method)
# 
#     def get_operations(self):
#         for method in METHODS:
#             if method in self.mapping:
#                 yield self.get_operation(method)
# 
# Path: lepo/apidef/version.py
# OPENAPI_3 = 'openapi3'
# 
# SWAGGER_2 = 'swagger2'
# 
# def parse_version(doc_dict):
#     if 'swagger' in doc_dict:
#         version = split_version(doc_dict['swagger'])
#         if version[0] != 2:  # pragma: no cover
#             raise ValueError('Only Swagger 2.x is supported')
#         return SWAGGER_2
#     elif 'openapi' in doc_dict:
#         version = split_version(doc_dict['openapi'])
#         if version[0] != 3:  # pragma: no cover
#             raise ValueError('Only OpenAPI 3.x is supported')
#         return OPENAPI_3
#     raise ValueError('API document is missing version specifier')
# 
# Path: lepo/utils.py
# def maybe_resolve(object, resolve):
#     """
#     Call `resolve` on the `object`'s `$ref` value if it has one.
# 
#     :param object: An object.
#     :param resolve: A resolving function.
#     :return: An object, or some other object! :sparkles:
#     """
#     if isinstance(object, dict) and object.get('$ref'):
#         return resolve(object['$ref'])
#     return object


from jsonschema import RefResolver
from lepo.apidef.operation.openapi import OpenAPI3Operation
from lepo.apidef.operation.swagger import Swagger2Operation
from lepo.apidef.path import Path
from lepo.apidef.version import OPENAPI_3, SWAGGER_2, parse_version
from lepo.utils import maybe_resolve
        from yaml import safe_load
                import yaml
                import json
        Construct an APIDefinition by parsing the given `filename`.

        If PyYAML is installed, YAML files are supported.
        JSON files are always supported.

        :param filename: The filename to read.
        :rtype: APIDefinition
        """
        with open(filename) as infp:
            if filename.endswith('.yaml') or filename.endswith('.yml'):
                data = yaml.safe_load(infp)
            else:
                data = json.load(infp)
        return cls.from_data(data)

    @classmethod
    def from_data(cls, data):
        version = parse_version(data)
        if version == SWAGGER_2:
            return Swagger2APIDefinition(data)
        if version == OPENAPI_3:
            return OpenAPI3APIDefinition(data)
        raise NotImplementedError('We can never get here.')  # pragma: no cover

    @classmethod
    def from_yaml(cls, yaml_string):
        return cls.from_data(safe_load(yaml_string))


class Swagger2APIDefinition(APIDefinition):

# Path: lepo/apidef/operation/openapi.py
# class OpenAPI3Operation(Operation):
#     parameter_class = OpenAPI3Parameter
#     body_parameter_class = OpenAPI3BodyParameter
# 
#     def _get_body_parameter(self):
#         for source in (
#             self.path.mapping.get('requestBody'),
#             self.data.get('requestBody'),
#         ):
#             if source:
#                 source = maybe_resolve(source, self.api.resolve_reference)
#                 body_parameter = self.body_parameter_class(data=source, operation=self, api=self.api)
#                 # TODO: Document x-lepo-body-name
#                 body_parameter.name = self.data.get('x-lepo-body-name', body_parameter.name)
#                 return body_parameter
# 
#     def get_parameter_dict(self):
#         parameter_dict = super().get_parameter_dict()
#         for parameter in parameter_dict.values():
#             if parameter.in_body:  # pragma: no cover
#                 raise ValueError('Regular parameter declared to be in body while parsing OpenAPI 3')
#         body_parameter = self._get_body_parameter()
#         if body_parameter:
#             parameter_dict[body_parameter.name] = body_parameter
#         return parameter_dict
# 
# Path: lepo/apidef/operation/swagger.py
# class Swagger2Operation(Operation):
#     parameter_class = Swagger2Parameter
# 
#     @cached_property
#     def consumes(self):
#         value = self._get_overridable('consumes', [])
#         if not isinstance(value, (list, tuple)):
#             raise TypeError(f'`consumes` must be a list, got {value!r}')  # pragma: no cover
#         return value
# 
#     @cached_property
#     def produces(self):
#         value = self._get_overridable('produces', [])
#         if not isinstance(value, (list, tuple)):
#             raise TypeError(f'`produces` must be a list, got {value!r}')  # pragma: no cover
#         return value
# 
# Path: lepo/apidef/path.py
# class Path:
#     def __init__(self, api, path, mapping):
#         """
#         :type api: lepo.apidef.APIDefinition
#         :type path: str
#         :type mapping: dict
#         """
#         self.api = api
#         self.path = path
#         self.mapping = mapping
#         self.regex = self._build_regex()
#         self.name = self._build_view_name()
# 
#     def get_view_class(self, router):
#         return type(f'{self.name.title()}View', (PathView,), {
#             'path': self,
#             'router': router,
#         })
# 
#     def _build_view_name(self):
#         path = re.sub(PATH_PLACEHOLDER_REGEX, r'\1', self.path)
#         name = re.sub(r'[^a-z0-9]+', '-', path, flags=re.I).strip('-').lower()
#         return name
# 
#     def _build_regex(self):
#         return re.sub(
#             PATH_PLACEHOLDER_REGEX,
#             lambda m: f'(?P<{m.group(1)}>[^/]+?)',
#             self.path,
#         ).lstrip('/') + '$'
# 
#     def get_operation(self, method):
#         operation_data = self.mapping.get(method.lower())
#         if not operation_data:
#             raise InvalidOperation(f'Path {self.path} does not support method {method.upper()}')
#         return self.api.operation_class(api=self.api, path=self, data=operation_data, method=method)
# 
#     def get_operations(self):
#         for method in METHODS:
#             if method in self.mapping:
#                 yield self.get_operation(method)
# 
# Path: lepo/apidef/version.py
# OPENAPI_3 = 'openapi3'
# 
# SWAGGER_2 = 'swagger2'
# 
# def parse_version(doc_dict):
#     if 'swagger' in doc_dict:
#         version = split_version(doc_dict['swagger'])
#         if version[0] != 2:  # pragma: no cover
#             raise ValueError('Only Swagger 2.x is supported')
#         return SWAGGER_2
#     elif 'openapi' in doc_dict:
#         version = split_version(doc_dict['openapi'])
#         if version[0] != 3:  # pragma: no cover
#             raise ValueError('Only OpenAPI 3.x is supported')
#         return OPENAPI_3
#     raise ValueError('API document is missing version specifier')
# 
# Path: lepo/utils.py
# def maybe_resolve(object, resolve):
#     """
#     Call `resolve` on the `object`'s `$ref` value if it has one.
# 
#     :param object: An object.
#     :param resolve: A resolving function.
#     :return: An object, or some other object! :sparkles:
#     """
#     if isinstance(object, dict) and object.get('$ref'):
#         return resolve(object['$ref'])
#     return object


# Path: lepo/apidef/doc.py
from jsonschema import RefResolver
from lepo.apidef.operation.openapi import OpenAPI3Operation
from lepo.apidef.operation.swagger import Swagger2Operation
from lepo.apidef.path import Path
from lepo.apidef.version import OPENAPI_3, SWAGGER_2, parse_version
from lepo.utils import maybe_resolve
        from yaml import safe_load
                import yaml
                import json

        Construct an APIDefinition by parsing the given `filename`.

        If PyYAML is installed, YAML files are supported.
        JSON files are always supported.

        :param filename: The filename to read.
        :rtype: APIDefinition
        """
        with open(filename) as infp:
            if filename.endswith('.yaml') or filename.endswith('.yml'):
                data = yaml.safe_load(infp)
            else:
                data = json.load(infp)
        return cls.from_data(data)

    @classmethod
    def from_data(cls, data):
        version = parse_version(data)
        if version == SWAGGER_2:
            return Swagger2APIDefinition(data)
        if version == OPENAPI_3:
            return OpenAPI3APIDefinition(data)
        raise NotImplementedError('We can never get here.')  # pragma: no cover

    @classmethod
    def from_yaml(cls, yaml_string):
        return cls.from_data(safe_load(yaml_string))


class Swagger2APIDefinition(APIDefinition):

    version = SWAGGER_2