openapi-parser 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. openapi_parser-0.3.0/LICENSE +25 -0
  2. openapi_parser-0.3.0/PKG-INFO +129 -0
  3. openapi_parser-0.3.0/README.md +71 -0
  4. openapi_parser-0.3.0/pyproject.toml +3 -0
  5. openapi_parser-0.3.0/requirements.txt +11 -0
  6. openapi_parser-0.3.0/setup.cfg +4 -0
  7. openapi_parser-0.3.0/setup.py +29 -0
  8. openapi_parser-0.3.0/src/openapi_parser/__init__.py +26 -0
  9. openapi_parser-0.3.0/src/openapi_parser/__main__.py +5 -0
  10. openapi_parser-0.3.0/src/openapi_parser/cli.py +103 -0
  11. openapi_parser-0.3.0/src/openapi_parser/exporter/__init__.py +40 -0
  12. openapi_parser-0.3.0/src/openapi_parser/exporter/abstract_writer.py +154 -0
  13. openapi_parser-0.3.0/src/openapi_parser/exporter/attribute_writer.py +75 -0
  14. openapi_parser-0.3.0/src/openapi_parser/exporter/class_writer.py +125 -0
  15. openapi_parser-0.3.0/src/openapi_parser/exporter/client_writer.py +296 -0
  16. openapi_parser-0.3.0/src/openapi_parser/exporter/description_writer.py +110 -0
  17. openapi_parser-0.3.0/src/openapi_parser/exporter/exporting_features/__init__.py +1 -0
  18. openapi_parser-0.3.0/src/openapi_parser/exporter/exporting_features/client.py +37 -0
  19. openapi_parser-0.3.0/src/openapi_parser/exporter/exporting_features/utils.py +4 -0
  20. openapi_parser-0.3.0/src/openapi_parser/exporter/footer_writer.py +63 -0
  21. openapi_parser-0.3.0/src/openapi_parser/exporter/header_writer.py +55 -0
  22. openapi_parser-0.3.0/src/openapi_parser/exporter/inspect_writer.py +127 -0
  23. openapi_parser-0.3.0/src/openapi_parser/exporter/method_writer.py +245 -0
  24. openapi_parser-0.3.0/src/openapi_parser/exporter/model_writer.py +99 -0
  25. openapi_parser-0.3.0/src/openapi_parser/exporter/pacakge_init_writer.py +129 -0
  26. openapi_parser-0.3.0/src/openapi_parser/exporter/package_writer.py +174 -0
  27. openapi_parser-0.3.0/src/openapi_parser/exporter/utils_writer.py +78 -0
  28. openapi_parser-0.3.0/src/openapi_parser/model.py +359 -0
  29. openapi_parser-0.3.0/src/openapi_parser/parser/__init__.py +30 -0
  30. openapi_parser-0.3.0/src/openapi_parser/parser/date_formats.py +65 -0
  31. openapi_parser-0.3.0/src/openapi_parser/parser/errors.py +77 -0
  32. openapi_parser-0.3.0/src/openapi_parser/parser/filters.py +308 -0
  33. openapi_parser-0.3.0/src/openapi_parser/parser/inheritance_support.py +166 -0
  34. openapi_parser-0.3.0/src/openapi_parser/parser/loader.py +547 -0
  35. openapi_parser-0.3.0/src/openapi_parser/parser/model_impl.py +543 -0
  36. openapi_parser-0.3.0/src/openapi_parser/parser/path.py +116 -0
  37. openapi_parser-0.3.0/src/openapi_parser/util/__init__.py +1 -0
  38. openapi_parser-0.3.0/src/openapi_parser/util/_backports.py +21 -0
  39. openapi_parser-0.3.0/src/openapi_parser/util/naming_conventions.py +57 -0
  40. openapi_parser-0.3.0/src/openapi_parser/util/typing_proxy.py +257 -0
  41. openapi_parser-0.3.0/src/openapi_parser/util/utils.py +95 -0
  42. openapi_parser-0.3.0/src/openapi_parser.egg-info/PKG-INFO +129 -0
  43. openapi_parser-0.3.0/src/openapi_parser.egg-info/SOURCES.txt +43 -0
  44. openapi_parser-0.3.0/src/openapi_parser.egg-info/dependency_links.txt +1 -0
  45. openapi_parser-0.3.0/src/openapi_parser.egg-info/requires.txt +25 -0
  46. openapi_parser-0.3.0/src/openapi_parser.egg-info/top_level.txt +1 -0
@@ -0,0 +1,25 @@
1
+ BSD 2-Clause License
2
+
3
+ Copyright (c) 2021-2026, Peter Zaitcev
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,129 @@
1
+ Metadata-Version: 2.4
2
+ Name: openapi-parser
3
+ Version: 0.3.0
4
+ Summary: OpenAPI 3.0 specs parser and client/server generator
5
+ Home-page: https://gitlab.com/Hares-Lab/libraries/openapi-parser
6
+ Author: Peter Zaitcev / USSX Hares
7
+ Maintainer: Peter Zaitcev / USSX Hares
8
+ License: BSD 2-Clause License
9
+ Classifier: Development Status :: 2 - Pre-Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Natural Language :: English
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3.7
14
+ Classifier: Programming Language :: Python :: 3.8
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Topic :: Software Development :: Code Generators
22
+ Classifier: Topic :: Software Development :: Libraries
23
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
+ Classifier: Topic :: Utilities
25
+ Classifier: Typing :: Typed
26
+ Requires-Python: >=3.7
27
+ Description-Content-Type: text/markdown
28
+ License-File: LICENSE
29
+ Requires-Dist: PyYAML~=6.0.1
30
+ Requires-Dist: functional-python~=0.4.0
31
+ Requires-Dist: http-server-base~=2.0.10
32
+ Requires-Dist: license~=0.1a3
33
+ Requires-Dist: stringcase~=1.2.0
34
+ Requires-Dist: tornado~=6.2; python_version <= "3.8"
35
+ Requires-Dist: tornado~=6.5; python_version >= "3.9"
36
+ Requires-Dist: backports.cached-property~=1.0.2; python_version < "3.8"
37
+ Requires-Dist: singledispatchmethod~=1.0; python_version < "3.8"
38
+ Provides-Extra: test
39
+ Requires-Dist: wheel; extra == "test"
40
+ Requires-Dist: lxml; extra == "test"
41
+ Requires-Dist: unittest-xml-reporting; extra == "test"
42
+ Provides-Extra: all
43
+ Requires-Dist: wheel; extra == "all"
44
+ Requires-Dist: lxml; extra == "all"
45
+ Requires-Dist: unittest-xml-reporting; extra == "all"
46
+ Dynamic: author
47
+ Dynamic: classifier
48
+ Dynamic: description
49
+ Dynamic: description-content-type
50
+ Dynamic: home-page
51
+ Dynamic: license
52
+ Dynamic: license-file
53
+ Dynamic: maintainer
54
+ Dynamic: provides-extra
55
+ Dynamic: requires-dist
56
+ Dynamic: requires-python
57
+ Dynamic: summary
58
+
59
+ # OpenAPI 3.0 Parser
60
+ This package provides functionality to analyze [OpenAPI 3.0 Specification] files
61
+ and build clients and servers from that specification.
62
+
63
+ For more details, please refer the [Project Documentation]
64
+
65
+ ### Example Usage
66
+ From the command line:
67
+ ```bash
68
+ $ python -m openapi_parser data/petstore.yaml
69
+ ```
70
+
71
+ From the Python:
72
+ ```python
73
+ from openapi_parser.exporter import PackageWriter
74
+ from openapi_parser.parser.loader import OpenApiParser
75
+
76
+ def main():
77
+ parser = OpenApiParser.open('data/petstore.yaml')
78
+ parser.load_all()
79
+
80
+ package_writer = PackageWriter(parser)
81
+ package_writer.write_package()
82
+
83
+ return 0
84
+
85
+ if (__name__ == '__main__'):
86
+ exit_code = main()
87
+ exit(exit_code)
88
+ ```
89
+
90
+ ### TODOs:
91
+ - [x] Model generator:
92
+ - [x] Core functionality
93
+ - [x] Class inheritance support
94
+ - [x] Enums support
95
+ - [ ] Required properties in combination with `readOnly`/`writeOnly`
96
+ - [x] Discriminator property support
97
+ - [ ] Cyclic refs resolution
98
+ - [ ] Support of `additionalProperties` inside class
99
+ - [x] Client generator
100
+ - [x] Core functionality
101
+ - [x] Smart body encoding
102
+ - [x] Smart response decoding
103
+ - [ ] `style`-encoding
104
+ - [ ] `schema` and `content` inside parameters conflict support
105
+ - [x] Enums for parameters support
106
+ - [ ] Cookies parameters support
107
+ - [x] Methods descriptions
108
+ - [ ] Authorization support
109
+ - [x] Metadata extractor
110
+ - [x] Version
111
+ - [x] Licence
112
+ - [x] Description
113
+ - [x] Servers
114
+ - [x] Security definitions
115
+ - [ ] Server generator
116
+ - [ ] Test coverage
117
+ - [ ] Documentation
118
+ - [x] Command-line interface
119
+ - [x] Basic CLI support
120
+ - [ ] Extended CLI support
121
+
122
+ ### See Also:
123
+ - [Project Documentation]
124
+ - [OpenAPI 3.0 Specification]
125
+ - [JSON Schema Standard]
126
+
127
+ [Project Documentation]: https://hares-lab.gitlab.io/openapi-parser
128
+ [OpenAPI 3.0 Specification]: https://swagger.io/specification
129
+ [JSON Schema Standard]: https://tools.ietf.org/html/draft-wright-json-schema-validation-00
@@ -0,0 +1,71 @@
1
+ # OpenAPI 3.0 Parser
2
+ This package provides functionality to analyze [OpenAPI 3.0 Specification] files
3
+ and build clients and servers from that specification.
4
+
5
+ For more details, please refer the [Project Documentation]
6
+
7
+ ### Example Usage
8
+ From the command line:
9
+ ```bash
10
+ $ python -m openapi_parser data/petstore.yaml
11
+ ```
12
+
13
+ From the Python:
14
+ ```python
15
+ from openapi_parser.exporter import PackageWriter
16
+ from openapi_parser.parser.loader import OpenApiParser
17
+
18
+ def main():
19
+ parser = OpenApiParser.open('data/petstore.yaml')
20
+ parser.load_all()
21
+
22
+ package_writer = PackageWriter(parser)
23
+ package_writer.write_package()
24
+
25
+ return 0
26
+
27
+ if (__name__ == '__main__'):
28
+ exit_code = main()
29
+ exit(exit_code)
30
+ ```
31
+
32
+ ### TODOs:
33
+ - [x] Model generator:
34
+ - [x] Core functionality
35
+ - [x] Class inheritance support
36
+ - [x] Enums support
37
+ - [ ] Required properties in combination with `readOnly`/`writeOnly`
38
+ - [x] Discriminator property support
39
+ - [ ] Cyclic refs resolution
40
+ - [ ] Support of `additionalProperties` inside class
41
+ - [x] Client generator
42
+ - [x] Core functionality
43
+ - [x] Smart body encoding
44
+ - [x] Smart response decoding
45
+ - [ ] `style`-encoding
46
+ - [ ] `schema` and `content` inside parameters conflict support
47
+ - [x] Enums for parameters support
48
+ - [ ] Cookies parameters support
49
+ - [x] Methods descriptions
50
+ - [ ] Authorization support
51
+ - [x] Metadata extractor
52
+ - [x] Version
53
+ - [x] Licence
54
+ - [x] Description
55
+ - [x] Servers
56
+ - [x] Security definitions
57
+ - [ ] Server generator
58
+ - [ ] Test coverage
59
+ - [ ] Documentation
60
+ - [x] Command-line interface
61
+ - [x] Basic CLI support
62
+ - [ ] Extended CLI support
63
+
64
+ ### See Also:
65
+ - [Project Documentation]
66
+ - [OpenAPI 3.0 Specification]
67
+ - [JSON Schema Standard]
68
+
69
+ [Project Documentation]: https://hares-lab.gitlab.io/openapi-parser
70
+ [OpenAPI 3.0 Specification]: https://swagger.io/specification
71
+ [JSON Schema Standard]: https://tools.ietf.org/html/draft-wright-json-schema-validation-00
@@ -0,0 +1,3 @@
1
+ [build-system]
2
+ requires = ['setuptools', 'extended-setup-tools >= 0.2.6']
3
+ build-backend = 'setuptools.build_meta'
@@ -0,0 +1,11 @@
1
+ PyYAML ~= 6.0.1
2
+ functional-python ~= 0.4.0
3
+ http-server-base ~= 2.0.10
4
+ license ~= 0.1a3
5
+ stringcase ~= 1.2.0
6
+ tornado ~= 6.2 ; python_version <= "3.8"
7
+ tornado ~= 6.5 ; python_version >= "3.9"
8
+
9
+ # Backports
10
+ backports.cached-property ~= 1.0.2 ; python_version < "3.8"
11
+ singledispatchmethod ~= 1.0 ; python_version < "3.8"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,29 @@
1
+ from extended_setup import ExtendedSetupManager
2
+
3
+
4
+ ExtendedSetupManager('openapi-parser').setup \
5
+ (
6
+ license = "BSD 2-Clause License",
7
+ short_description = "OpenAPI 3.0 specs parser and client/server generator",
8
+ min_python_version = '3.7',
9
+ classifiers =
10
+ [
11
+ 'Development Status :: 2 - Pre-Alpha',
12
+ 'Intended Audience :: Developers',
13
+ 'Natural Language :: English',
14
+ 'Operating System :: OS Independent',
15
+ 'Programming Language :: Python :: 3.7',
16
+ 'Programming Language :: Python :: 3.8',
17
+ 'Programming Language :: Python :: 3.9',
18
+ 'Programming Language :: Python :: 3.10',
19
+ 'Programming Language :: Python :: 3.11',
20
+ 'Programming Language :: Python :: 3.12',
21
+ 'Programming Language :: Python :: 3.13',
22
+ 'Programming Language :: Python :: 3.14',
23
+ 'Topic :: Software Development :: Code Generators',
24
+ 'Topic :: Software Development :: Libraries',
25
+ 'Topic :: Software Development :: Libraries :: Python Modules',
26
+ 'Topic :: Utilities',
27
+ 'Typing :: Typed',
28
+ ]
29
+ )
@@ -0,0 +1,26 @@
1
+ """
2
+ .. include:: ../../README.md
3
+ """
4
+
5
+ from collections import namedtuple
6
+
7
+ __title__ = 'openapi-parser'
8
+ __author__ = 'Peter Zaitcev / USSX Hares'
9
+ __license__ = 'BSD 2-clause'
10
+ __copyright__ = 'Copyright 2020-2026 Peter Zaitcev'
11
+ __version__ = '0.3.0'
12
+
13
+ VersionInfo = namedtuple('VersionInfo', 'major minor micro releaselevel serial')
14
+ version_info = VersionInfo(*__version__.split('.'), releaselevel='alpha', serial=0)
15
+
16
+ __all__ = \
17
+ [
18
+ 'version_info',
19
+ '__title__',
20
+ '__author__',
21
+ '__license__',
22
+ '__copyright__',
23
+ '__version__',
24
+ ]
25
+ __pdoc__ = { }
26
+ __pdoc_extras__ = [ ]
@@ -0,0 +1,5 @@
1
+ from openapi_parser.cli import cli
2
+
3
+ if (__name__ == '__main__'):
4
+ exit_code = cli()
5
+ exit(exit_code)
@@ -0,0 +1,103 @@
1
+ import sys
2
+ from logging import getLogger, StreamHandler
3
+ from typing import *
4
+
5
+ from .__init__ import __version__, __title__
6
+ from .exporter import PackageWriter
7
+ from .model import HavingId
8
+ from .parser.loader import *
9
+ from .util.utils import list_pop_any
10
+
11
+ JUSTIFICATION_SIZE = 140
12
+ def get_logger(verbose: bool = False):
13
+ logger = getLogger('openapi-parser')
14
+ handler = StreamHandler(sys.stdout)
15
+ logger.addHandler(handler)
16
+ if (verbose):
17
+ handler.setLevel('DEBUG')
18
+ logger.setLevel('DEBUG')
19
+ else:
20
+ handler.setLevel('INFO')
21
+ logger.setLevel('INFO')
22
+
23
+ return logger
24
+
25
+ def run(schema_file: str, *writer_args, verbose: bool = False, dry_run: bool = False, clean: bool = True) -> int:
26
+ logger = get_logger(verbose=verbose)
27
+
28
+ parser = OpenApiParser.open(schema_file)
29
+ parser.load_all()
30
+
31
+ for path, mdl in parser.loaded_objects.items():
32
+ msg = ('# ' + type(mdl).__name__ + (f" '{mdl.id}'" if isinstance(mdl, HavingId) else '')).ljust(JUSTIFICATION_SIZE, ' ') + f" -- '{path}'"
33
+ logger.debug(msg)
34
+ logger.debug('# ' + '=' * JUSTIFICATION_SIZE)
35
+ logger.debug('')
36
+
37
+ package_writer = PackageWriter(parser, *writer_args, dry_run=dry_run)
38
+ package_writer.write_package(clean=clean)
39
+ return 0
40
+
41
+ def header_line() -> str:
42
+ return f"Python OpenAPI Parser Command-Line Interface v{__version__}"
43
+ def version_line() -> str:
44
+ return f"{__title__} {__version__}"
45
+ def usage_line() -> str:
46
+ return 'python -m openapi_parser SCHEMA [DESTINATION] [PACKAGE_NAME]'
47
+ def usage_options() -> List[str]:
48
+ return \
49
+ [
50
+ "-v, --verbose | Enables extra verbosity",
51
+ "--dry-run | Performs dry run (does not create any files)",
52
+ "--no-cleanup | Does not perform cleanup before running",
53
+ "-h, --help -? | Print this message and exit",
54
+ "-V, --version | Print version and exit",
55
+ ]
56
+
57
+ def cli(args: Optional[List[str]] = None) -> int:
58
+ if (args is None):
59
+ args = sys.argv[1:]
60
+
61
+ if (len(args) < 1):
62
+ print(header_line(), file=sys.stderr)
63
+ print(f"Not enough arguments, usage: {usage_line()}", file=sys.stderr)
64
+ return 1
65
+
66
+ help = bool(list_pop_any(args, '-h', '--help', '-?'))
67
+ if (help):
68
+ print(header_line())
69
+ print(f"Usage: {usage_line()}")
70
+ print()
71
+ print("Options:")
72
+ for opt in usage_options():
73
+ print(' '*4 + opt)
74
+ return 0
75
+
76
+ version = bool(list_pop_any(args, '-V', '--version'))
77
+ if (version):
78
+ print(version_line())
79
+ return 0
80
+
81
+ verbose = bool(list_pop_any(args, '-v', '--verbose'))
82
+ dry_run = bool(list_pop_any(args, '--dry-run'))
83
+ clean = not bool(list_pop_any(args, '--no-cleanup'))
84
+ schema_file = args.pop(0)
85
+
86
+ return run(schema_file, *args, verbose=verbose, dry_run=dry_run, clean=clean)
87
+
88
+
89
+ __all__ = \
90
+ [
91
+ 'cli',
92
+ 'run',
93
+ 'get_logger',
94
+ 'usage_options',
95
+ 'version_line',
96
+ 'header_line',
97
+ 'usage_line',
98
+ 'JUSTIFICATION_SIZE',
99
+ ]
100
+ __pdoc_extras__ = \
101
+ [
102
+ 'JUSTIFICATION_SIZE',
103
+ ]
@@ -0,0 +1,40 @@
1
+ from .abstract_writer import *
2
+ from .attribute_writer import *
3
+ from .class_writer import *
4
+ from .client_writer import *
5
+ from .description_writer import *
6
+ from .footer_writer import *
7
+ from .header_writer import *
8
+ from .inspect_writer import *
9
+ from .method_writer import *
10
+ from .model_writer import *
11
+ from .package_writer import *
12
+ from .utils_writer import *
13
+
14
+ __all__ = [ ]
15
+
16
+ _submodules = \
17
+ [
18
+ abstract_writer,
19
+ attribute_writer,
20
+ class_writer,
21
+ client_writer,
22
+ description_writer,
23
+ footer_writer,
24
+ header_writer,
25
+ inspect_writer,
26
+ method_writer,
27
+ model_writer,
28
+ package_writer,
29
+ utils_writer,
30
+ ]
31
+
32
+ __pdoc__ = { }
33
+ for _submodule in _submodules:
34
+ _submodule_name = _submodule.__name__.partition(f'{__name__}.')[-1]
35
+ __all__.extend(_submodule.__all__)
36
+ __pdoc__[_submodule_name] = True
37
+ _submodule.__pdoc__ = getattr(_submodule, '__pdoc__', dict())
38
+ _extras = getattr(_submodule, '__pdoc_extras__', list())
39
+ for _element in _submodule.__all__:
40
+ __pdoc__[_element] = _element in _extras
@@ -0,0 +1,154 @@
1
+ from __future__ import annotations
2
+
3
+ import keyword
4
+ import re
5
+ from abc import ABC
6
+ from dataclasses import dataclass
7
+ from functools import wraps, partial
8
+ from logging import Logger, getLogger
9
+ from typing import *
10
+
11
+ from openapi_parser.model import Model, Filter
12
+ from openapi_parser.util._backports import singledispatchmethod
13
+ from openapi_parser.util.naming_conventions import *
14
+ from openapi_parser.util.typing_proxy import ref_name_pretty, class_name_pretty, GenericProxy, ref_name_logger
15
+ from openapi_parser.util.utils import StrIO
16
+
17
+ W = TypeVar('W', bound='Writer')
18
+ class Writer(ABC):
19
+ JUSTIFICATION_SIZE = 80
20
+ INDENT_SIZE = 4
21
+ INDENT_SYMBOL = ' '
22
+ TRIPLE_QUOT = '"""'
23
+ TRIPLE_BACKQUOT = '```'
24
+ NEWLINE = '\n'
25
+
26
+ _indent_level: int
27
+ logger: Logger
28
+ def __init__(self, *args, **kwargs):
29
+ self._indent_level = 0
30
+ self.logger = getLogger(ref_name_logger(type(self)))
31
+ super().__init__(*args, **kwargs)
32
+
33
+ @property
34
+ def indent_level(self) -> int:
35
+ return self._indent_level
36
+
37
+ @property
38
+ def indent_marker(self) -> str:
39
+ return self.INDENT_SYMBOL * self.INDENT_SIZE
40
+
41
+ def indent(self, increment: int = 1) -> 'Indenting[W]':
42
+ return Indenting(self, increment)
43
+
44
+ @classmethod
45
+ def class_name_pretty(cls, ref: Union[str, Type, GenericProxy, Model, Filter]) -> str:
46
+ if (isinstance(ref, str)):
47
+ return class_name(ref)
48
+ else:
49
+ return class_name_pretty(ref)
50
+ @classmethod
51
+ def package_name_pretty(cls, name: str) -> str:
52
+ return package_name(name)
53
+ @classmethod
54
+ def enum_entry_name_pretty(cls, name: str) -> str:
55
+ return enum_entry_name(name)
56
+ @classmethod
57
+ def field_name_pretty(cls, name: str) -> str:
58
+ return field_name(name)
59
+ @classmethod
60
+ def method_name_pretty(cls, name: str) -> str:
61
+ return method_name(name)
62
+ @classmethod
63
+ def const_name_pretty(cls, name: str) -> str:
64
+ return const_name(name)
65
+ @classmethod
66
+ def ref_name_pretty(cls, ref: Union[object, str], full: bool = False) -> str:
67
+ if (isinstance(ref, str)):
68
+ return ref
69
+ else:
70
+ return ref_name_pretty(ref, full=full)
71
+ @classmethod
72
+ def object_valid_name_filter(cls, name: str) -> str:
73
+ if (not re.fullmatch(r'\w+', name)):
74
+ name = re.sub(r'[\W_]+', '_', name).strip('_')
75
+ if (not name):
76
+ name += '_'
77
+ if (name[0].isdigit()):
78
+ name = 'OBJECT_' + name
79
+ if (name in keyword.kwlist):
80
+ name += '_'
81
+
82
+ return name
83
+ @classmethod
84
+ def constructor(cls, prefix: str, *args, suffix: str = '', sep: str = '=', brackets: Tuple[str, str] = ('(', ')'), **kwargs) -> str:
85
+ return prefix + brackets[0] + ', '.join(list(args) + [ f'{k}{sep}{v}' for k, v in kwargs.items() ]) + brackets[1] + suffix
86
+ @classmethod
87
+ def dict_constructor(cls, **kwargs) -> str:
88
+ return cls.constructor('', sep=': ', brackets=('{', '}'), **{ repr(k): v for k, v in kwargs.items() })
89
+ def multiline_constructor(self, prefix: str, *args, suffix: str = '', sep: str = ' = ', brackets: Tuple[str, str] = ('(', ')'), **kwargs) -> Iterator[str]:
90
+ yield f'{prefix} \\'
91
+ yield brackets[0]
92
+ with self.indent():
93
+ for x in args:
94
+ yield f'{x},'
95
+ for k, v in kwargs.items():
96
+ yield f'{k}{sep}{v},'
97
+ yield brackets[1] + suffix
98
+ def smart_constructor(self, prefix: str, *args, suffix: str = '', **kwargs) -> Iterator[str]:
99
+ inline = self.constructor(prefix, *args, suffix=suffix, **kwargs)
100
+ if (len(inline) < 160):
101
+ yield inline
102
+ else:
103
+ yield from self.multiline_constructor(prefix, *args, suffix=suffix, **kwargs)
104
+
105
+ @singledispatchmethod
106
+ def join_line(self, indent_level: int, line_text: str) -> str:
107
+ return self.indent_marker * indent_level + line_text
108
+ @join_line.register
109
+ def _(self, tup: tuple) -> str:
110
+ return self.join_line(*tup)
111
+
112
+ def write_line(self, file: StrIO, line: str):
113
+ file.write(line)
114
+ file.write(self.NEWLINE)
115
+
116
+ # noinspection PyProtectedMember
117
+ @dataclass
118
+ class Indenting(ContextManager, Generic[W]):
119
+ writer: W
120
+ increment: int = 1
121
+
122
+ def __enter__(self):
123
+ self.writer._indent_level += self.increment
124
+ def __exit__(self, exc_type, exc_val, exc_tb):
125
+ self.writer._indent_level -= self.increment
126
+
127
+ def yielder(dumper_func: Callable[[W], Iterator[Optional[str]]]) -> Callable[[W], Iterator[Tuple[int, str]]]:
128
+ @wraps(dumper_func)
129
+ def wrapper(self: Writer, *args, **kwargs):
130
+ # noinspection PyArgumentList
131
+ return map(lambda line: (self.indent_level, line or ''), dumper_func(self, *args, **kwargs))
132
+ return wrapper
133
+
134
+ def writer(yielder_func: Callable[[W], Iterator[Tuple[int, str]]]) -> Callable[[W], Optional[Iterator[str]]]:
135
+ @wraps(yielder_func)
136
+ def wrapper(self: Writer, *args, file: StrIO | None = None, **kwargs):
137
+ # noinspection PyArgumentList
138
+ stream = map(self.join_line, yielder_func(self, *args, **kwargs))
139
+ if (file is not None):
140
+ list(map(partial(self.write_line, file), stream))
141
+ else:
142
+ return stream
143
+
144
+ return wrapper
145
+
146
+
147
+ __all__ = \
148
+ [
149
+ 'Indenting',
150
+ 'Writer',
151
+
152
+ 'writer',
153
+ 'yielder',
154
+ ]
@@ -0,0 +1,75 @@
1
+ from abc import ABC
2
+ from typing import *
3
+
4
+ from functional import OptionNone, Some, Option
5
+
6
+ from openapi_parser.model import ModelSchema
7
+ from openapi_parser.util.typing_proxy import GenericProxy
8
+ from .abstract_writer import Writer
9
+
10
+ class AttributeWriter(Writer, ABC):
11
+ def parse_attribute(self, name: str, prop: Optional[ModelSchema], *, is_required: bool = True) -> Tuple[str, Option[str], Option[str], Option[str]]:
12
+ field_name_pretty = self.field_name_pretty(name)
13
+ actual_name = self.object_valid_name_filter(field_name_pretty)
14
+
15
+ if (prop is None):
16
+ f_type = Some('Optional[Any]') if (not is_required) else OptionNone
17
+ f_value = Some('None') if (not is_required) else OptionNone
18
+ f_default = Some('None') if (not is_required) else OptionNone
19
+
20
+ else:
21
+ if (prop.cls == Any):
22
+ f_type = OptionNone
23
+ else:
24
+ f_type = Some(self.class_name_pretty(prop.cls)) if isinstance(prop, ModelSchema) else OptionNone
25
+ f_default = prop.default
26
+
27
+ # for enum in find_filters(prop.filter, ModelEnumData):
28
+ # f_type = Some(self.object_valid_name_filter(self.class_name_pretty(enum)))
29
+
30
+ if (not is_required):
31
+ f_type = f_type.map('Optional[{}]'.format)
32
+ f_default = f_default or (Some(None) if (not is_required) else OptionNone)
33
+
34
+ f_value = f_default.map('{!r}'.format)
35
+
36
+ return actual_name, f_type, f_value, f_default
37
+
38
+ def join_attribute(self, actual_name: str, f_type: Option[str], f_value: Option[str]) -> str:
39
+ return actual_name + f_type.map(': {}'.format).get_or_else('') + f_value.map(' = {}'.format).get_or_else('')
40
+
41
+ def extract_generic_coder(self, generic: GenericProxy, coder_type: str) -> Optional[str]:
42
+ parsed = generic.deep_coder(coder_type)
43
+ if (parsed is None):
44
+ return None
45
+
46
+ return 'lambda x: ' + self._extract_generic_coder('x', *parsed)
47
+
48
+ def _extract_generic_coder(self, super_var: str, gen: GenericProxy, params: Dict[str, Optional[Union[Tuple, Callable, str, None]]]) -> str:
49
+ items = list()
50
+ for var, coder in params.items():
51
+ if (coder is None):
52
+ coder = var
53
+ elif (isinstance(coder, tuple)):
54
+ coder = Option(self._extract_generic_coder(var, *coder)).map(lambda x: x + f'({var})').get_or_else(var)
55
+ else:
56
+ coder = self.ref_name_pretty(coder)
57
+
58
+ items.append(coder)
59
+
60
+ return gen.constructor(f"{gen.item_constructor(tuple(items))} for {', '.join(params.keys())} in {gen.iterator(super_var)}")
61
+
62
+ def extract_coder(self, prop: ModelSchema, coder_type: str) -> Optional[str]:
63
+ coder = getattr(prop.filter, coder_type)
64
+ if (coder is not None):
65
+ return self.ref_name_pretty(coder)
66
+ elif (isinstance(prop.cls, GenericProxy)):
67
+ return self.extract_generic_coder(prop.cls, coder_type)
68
+ else:
69
+ return None
70
+
71
+
72
+ __all__ = \
73
+ [
74
+ 'AttributeWriter',
75
+ ]