eccodes 1.7.0__tar.gz → 2.37.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 (41) hide show
  1. {eccodes-1.7.0 → eccodes-2.37.0}/CHANGELOG.rst +11 -0
  2. {eccodes-1.7.0 → eccodes-2.37.0}/PKG-INFO +39 -4
  3. {eccodes-1.7.0 → eccodes-2.37.0}/README.rst +27 -3
  4. {eccodes-1.7.0 → eccodes-2.37.0}/eccodes.egg-info/PKG-INFO +39 -4
  5. {eccodes-1.7.0 → eccodes-2.37.0}/gribapi/__init__.py +2 -2
  6. eccodes-2.37.0/gribapi/bindings.py +117 -0
  7. {eccodes-1.7.0 → eccodes-2.37.0}/gribapi/gribapi.py +1 -1
  8. {eccodes-1.7.0 → eccodes-2.37.0}/setup.py +39 -0
  9. {eccodes-1.7.0 → eccodes-2.37.0}/tests/test_eccodes.py +3 -2
  10. eccodes-1.7.0/gribapi/bindings.py +0 -46
  11. {eccodes-1.7.0 → eccodes-2.37.0}/.dockerignore +0 -0
  12. {eccodes-1.7.0 → eccodes-2.37.0}/CONTRIBUTING.rst +0 -0
  13. {eccodes-1.7.0 → eccodes-2.37.0}/Dockerfile +0 -0
  14. {eccodes-1.7.0 → eccodes-2.37.0}/LICENSE +0 -0
  15. {eccodes-1.7.0 → eccodes-2.37.0}/MANIFEST.in +0 -0
  16. {eccodes-1.7.0 → eccodes-2.37.0}/Makefile +0 -0
  17. {eccodes-1.7.0 → eccodes-2.37.0}/builder.py +0 -0
  18. {eccodes-1.7.0 → eccodes-2.37.0}/docs/_static/.gitkeep +0 -0
  19. {eccodes-1.7.0 → eccodes-2.37.0}/docs/conf.py +0 -0
  20. {eccodes-1.7.0 → eccodes-2.37.0}/docs/index.rst +0 -0
  21. {eccodes-1.7.0 → eccodes-2.37.0}/eccodes/__init__.py +0 -0
  22. {eccodes-1.7.0 → eccodes-2.37.0}/eccodes/__main__.py +0 -0
  23. {eccodes-1.7.0 → eccodes-2.37.0}/eccodes/eccodes.py +0 -0
  24. {eccodes-1.7.0 → eccodes-2.37.0}/eccodes/highlevel/__init__.py +0 -0
  25. {eccodes-1.7.0 → eccodes-2.37.0}/eccodes/highlevel/message.py +0 -0
  26. {eccodes-1.7.0 → eccodes-2.37.0}/eccodes/highlevel/reader.py +0 -0
  27. {eccodes-1.7.0 → eccodes-2.37.0}/eccodes.egg-info/SOURCES.txt +0 -0
  28. {eccodes-1.7.0 → eccodes-2.37.0}/eccodes.egg-info/dependency_links.txt +0 -0
  29. {eccodes-1.7.0 → eccodes-2.37.0}/eccodes.egg-info/requires.txt +0 -0
  30. {eccodes-1.7.0 → eccodes-2.37.0}/eccodes.egg-info/top_level.txt +0 -0
  31. {eccodes-1.7.0 → eccodes-2.37.0}/eccodes.egg-info/zip-safe +0 -0
  32. {eccodes-1.7.0 → eccodes-2.37.0}/gribapi/eccodes.h +0 -0
  33. {eccodes-1.7.0 → eccodes-2.37.0}/gribapi/errors.py +0 -0
  34. {eccodes-1.7.0 → eccodes-2.37.0}/gribapi/grib_api.h +0 -0
  35. {eccodes-1.7.0 → eccodes-2.37.0}/setup.cfg +0 -0
  36. {eccodes-1.7.0 → eccodes-2.37.0}/tests/sample-data/era5-levels-members.grib +0 -0
  37. {eccodes-1.7.0 → eccodes-2.37.0}/tests/sample-data/tiggelam_cnmc_sfc.grib2 +0 -0
  38. {eccodes-1.7.0 → eccodes-2.37.0}/tests/test_20_main.py +0 -0
  39. {eccodes-1.7.0 → eccodes-2.37.0}/tests/test_20_messages.py +0 -0
  40. {eccodes-1.7.0 → eccodes-2.37.0}/tests/test_highlevel.py +0 -0
  41. {eccodes-1.7.0 → eccodes-2.37.0}/tox.ini +0 -0
@@ -2,8 +2,19 @@
2
2
  Changelog for eccodes-python
3
3
  ============================
4
4
 
5
+ 2.37.0 (2024-09-09)
6
+ -------------------
7
+
8
+ - bundle ecCodes binary library with the PyPi distribution, for Linux and MacOS
9
+
10
+ 1.7.1 (2024-06-19)
11
+ --------------------
12
+
13
+ - `np.Infinity` was removed in the NumPy 2.0 release
14
+
5
15
  1.7.0 (2024-02-26)
6
16
  --------------------
17
+
7
18
  - ECC-1761: Add function to extract message offsets and sizes
8
19
  - ECC-1742: Add function to clone only the meta-data of a message
9
20
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: eccodes
3
- Version: 1.7.0
3
+ Version: 2.37.0
4
4
  Summary: Python interface to the ecCodes GRIB and BUFR decoder/encoder
5
5
  Home-page: https://github.com/ecmwf/eccodes-python
6
6
  Author: European Centre for Medium-Range Weather Forecasts (ECMWF)
@@ -49,16 +49,40 @@ Limitations:
49
49
  Installation
50
50
  ============
51
51
 
52
+ **From version 2.37.0, the ecCodes Python bindings additionally provide the ecCodes binary library, and will
53
+ follow the version numbering of the ecCodes binary library. See below for details.**
54
+
55
+
52
56
  The package is installed from PyPI with::
53
57
 
54
58
  $ pip install eccodes
55
59
 
60
+ This installation will, by default, include the ecCodes binary library (as of version 2.37.0), meaning that no
61
+ external ecCodes binary library is required. If you have an external ecCodes binary library that you wish to use,
62
+ set the following environment variable before you import eccodes::
63
+
64
+ $ export ECCODES_PYTHON_USE_FINDLIBS=1
65
+
66
+ If this is set, the ecCodes' Python bindings will use the `findlibs <https://github.com/ecmwf/findlibs>`_ package
67
+ to locate the binary library (findlibs was the only mechanism used before version 2.37.0).
68
+
69
+ In order to gain insights into the search for the binary library, set the following environment variable before
70
+ importing eccodes::
71
+
72
+ $ export ECCODES_PYTHON_TRACE_LIB_SEARCH=1
73
+
74
+ You may also install a version of ecCodes' Python interface that does not include a binary library at all,
75
+ in which case the findlibs mechanism will be used as before::
76
+
77
+ $ pip install eccodes --no-binary eccodes
78
+
56
79
 
57
80
  System dependencies
58
81
  -------------------
59
82
 
60
- The Python module depends on the ECMWF *ecCodes* library
61
- that must be installed on the system and accessible as a shared library.
83
+ The Python module depends on the ECMWF *ecCodes* library. From version 2.37.0, this is supplied with
84
+ the Python module. If you wish to install and use a separate binary library (see above), it
85
+ must be installed on the system and accessible as a shared library.
62
86
 
63
87
  On a MacOS with HomeBrew use::
64
88
 
@@ -75,7 +99,7 @@ https://confluence.ecmwf.int/display/ECC/ecCodes+installation
75
99
  You may run a simple selfcheck command to ensure that your system is set up correctly::
76
100
 
77
101
  $ python -m eccodes selfcheck
78
- Found: ecCodes v2.27.0.
102
+ Found: ecCodes v2.37.0.
79
103
  Your system is ready.
80
104
 
81
105
 
@@ -155,8 +179,19 @@ does it submit to any jurisdiction.
155
179
  Changelog for eccodes-python
156
180
  ============================
157
181
 
182
+ 2.37.0 (2024-09-09)
183
+ -------------------
184
+
185
+ - bundle ecCodes binary library with the PyPi distribution, for Linux and MacOS
186
+
187
+ 1.7.1 (2024-06-19)
188
+ --------------------
189
+
190
+ - `np.Infinity` was removed in the NumPy 2.0 release
191
+
158
192
  1.7.0 (2024-02-26)
159
193
  --------------------
194
+
160
195
  - ECC-1761: Add function to extract message offsets and sizes
161
196
  - ECC-1742: Add function to clone only the meta-data of a message
162
197
 
@@ -24,16 +24,40 @@ Limitations:
24
24
  Installation
25
25
  ============
26
26
 
27
+ **From version 2.37.0, the ecCodes Python bindings additionally provide the ecCodes binary library, and will
28
+ follow the version numbering of the ecCodes binary library. See below for details.**
29
+
30
+
27
31
  The package is installed from PyPI with::
28
32
 
29
33
  $ pip install eccodes
30
34
 
35
+ This installation will, by default, include the ecCodes binary library (as of version 2.37.0), meaning that no
36
+ external ecCodes binary library is required. If you have an external ecCodes binary library that you wish to use,
37
+ set the following environment variable before you import eccodes::
38
+
39
+ $ export ECCODES_PYTHON_USE_FINDLIBS=1
40
+
41
+ If this is set, the ecCodes' Python bindings will use the `findlibs <https://github.com/ecmwf/findlibs>`_ package
42
+ to locate the binary library (findlibs was the only mechanism used before version 2.37.0).
43
+
44
+ In order to gain insights into the search for the binary library, set the following environment variable before
45
+ importing eccodes::
46
+
47
+ $ export ECCODES_PYTHON_TRACE_LIB_SEARCH=1
48
+
49
+ You may also install a version of ecCodes' Python interface that does not include a binary library at all,
50
+ in which case the findlibs mechanism will be used as before::
51
+
52
+ $ pip install eccodes --no-binary eccodes
53
+
31
54
 
32
55
  System dependencies
33
56
  -------------------
34
57
 
35
- The Python module depends on the ECMWF *ecCodes* library
36
- that must be installed on the system and accessible as a shared library.
58
+ The Python module depends on the ECMWF *ecCodes* library. From version 2.37.0, this is supplied with
59
+ the Python module. If you wish to install and use a separate binary library (see above), it
60
+ must be installed on the system and accessible as a shared library.
37
61
 
38
62
  On a MacOS with HomeBrew use::
39
63
 
@@ -50,7 +74,7 @@ https://confluence.ecmwf.int/display/ECC/ecCodes+installation
50
74
  You may run a simple selfcheck command to ensure that your system is set up correctly::
51
75
 
52
76
  $ python -m eccodes selfcheck
53
- Found: ecCodes v2.27.0.
77
+ Found: ecCodes v2.37.0.
54
78
  Your system is ready.
55
79
 
56
80
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: eccodes
3
- Version: 1.7.0
3
+ Version: 2.37.0
4
4
  Summary: Python interface to the ecCodes GRIB and BUFR decoder/encoder
5
5
  Home-page: https://github.com/ecmwf/eccodes-python
6
6
  Author: European Centre for Medium-Range Weather Forecasts (ECMWF)
@@ -49,16 +49,40 @@ Limitations:
49
49
  Installation
50
50
  ============
51
51
 
52
+ **From version 2.37.0, the ecCodes Python bindings additionally provide the ecCodes binary library, and will
53
+ follow the version numbering of the ecCodes binary library. See below for details.**
54
+
55
+
52
56
  The package is installed from PyPI with::
53
57
 
54
58
  $ pip install eccodes
55
59
 
60
+ This installation will, by default, include the ecCodes binary library (as of version 2.37.0), meaning that no
61
+ external ecCodes binary library is required. If you have an external ecCodes binary library that you wish to use,
62
+ set the following environment variable before you import eccodes::
63
+
64
+ $ export ECCODES_PYTHON_USE_FINDLIBS=1
65
+
66
+ If this is set, the ecCodes' Python bindings will use the `findlibs <https://github.com/ecmwf/findlibs>`_ package
67
+ to locate the binary library (findlibs was the only mechanism used before version 2.37.0).
68
+
69
+ In order to gain insights into the search for the binary library, set the following environment variable before
70
+ importing eccodes::
71
+
72
+ $ export ECCODES_PYTHON_TRACE_LIB_SEARCH=1
73
+
74
+ You may also install a version of ecCodes' Python interface that does not include a binary library at all,
75
+ in which case the findlibs mechanism will be used as before::
76
+
77
+ $ pip install eccodes --no-binary eccodes
78
+
56
79
 
57
80
  System dependencies
58
81
  -------------------
59
82
 
60
- The Python module depends on the ECMWF *ecCodes* library
61
- that must be installed on the system and accessible as a shared library.
83
+ The Python module depends on the ECMWF *ecCodes* library. From version 2.37.0, this is supplied with
84
+ the Python module. If you wish to install and use a separate binary library (see above), it
85
+ must be installed on the system and accessible as a shared library.
62
86
 
63
87
  On a MacOS with HomeBrew use::
64
88
 
@@ -75,7 +99,7 @@ https://confluence.ecmwf.int/display/ECC/ecCodes+installation
75
99
  You may run a simple selfcheck command to ensure that your system is set up correctly::
76
100
 
77
101
  $ python -m eccodes selfcheck
78
- Found: ecCodes v2.27.0.
102
+ Found: ecCodes v2.37.0.
79
103
  Your system is ready.
80
104
 
81
105
 
@@ -155,8 +179,19 @@ does it submit to any jurisdiction.
155
179
  Changelog for eccodes-python
156
180
  ============================
157
181
 
182
+ 2.37.0 (2024-09-09)
183
+ -------------------
184
+
185
+ - bundle ecCodes binary library with the PyPi distribution, for Linux and MacOS
186
+
187
+ 1.7.1 (2024-06-19)
188
+ --------------------
189
+
190
+ - `np.Infinity` was removed in the NumPy 2.0 release
191
+
158
192
  1.7.0 (2024-02-26)
159
193
  --------------------
194
+
160
195
  - ECC-1761: Add function to extract message offsets and sizes
161
196
  - ECC-1742: Add function to clone only the meta-data of a message
162
197
 
@@ -14,8 +14,8 @@ from .gribapi import * # noqa
14
14
  from .gribapi import __version__, lib
15
15
 
16
16
  # The minimum recommended version for the ecCodes package
17
- min_recommended_version_str = "2.31.0"
18
- min_recommended_version_int = 23100
17
+ min_recommended_version_str = "2.37.0"
18
+ min_recommended_version_int = 23700
19
19
 
20
20
  if lib.grib_get_api_version() < min_recommended_version_int:
21
21
  import warnings
@@ -0,0 +1,117 @@
1
+ #
2
+ # (C) Copyright 2017- ECMWF.
3
+ #
4
+ # This software is licensed under the terms of the Apache Licence Version 2.0
5
+ # which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6
+ #
7
+ # In applying this licence, ECMWF does not waive the privileges and immunities
8
+ # granted to it by virtue of its status as an intergovernmental organisation nor
9
+ # does it submit to any jurisdiction.
10
+ #
11
+
12
+ # Authors:
13
+ # Alessandro Amici - B-Open - https://bopen.eu
14
+ # Shahram Najm - ECMWF - https://www.ecmwf.int
15
+ #
16
+
17
+ from __future__ import absolute_import, division, print_function, unicode_literals
18
+
19
+ import logging
20
+ import os
21
+ import pkgutil
22
+ import sys
23
+
24
+ import cffi
25
+
26
+ __version__ = "2.37.0"
27
+
28
+ LOG = logging.getLogger(__name__)
29
+
30
+ _MAP = {
31
+ "grib_api": "eccodes",
32
+ "gribapi": "eccodes",
33
+ }
34
+
35
+ EXTENSIONS = {
36
+ "darwin": ".dylib",
37
+ "win32": ".dll",
38
+ }
39
+
40
+ # convenient way to trace the search for the library
41
+ if int(os.environ.get("ECCODES_PYTHON_TRACE_LIB_SEARCH", "0")):
42
+ LOG.setLevel(logging.DEBUG)
43
+ LOG.addHandler(logging.StreamHandler())
44
+
45
+
46
+ def _lookup(name):
47
+ return _MAP.get(name, name)
48
+
49
+
50
+ def find_binary_libs(name):
51
+
52
+ name = _lookup(name)
53
+ env_var = "ECCODES_PYTHON_USE_FINDLIBS"
54
+ if int(os.environ.get(env_var, "0")):
55
+ LOG.debug(f"{name} lib search: {env_var} set, so using findlibs")
56
+
57
+ else:
58
+ LOG.debug(f"{name} lib search: trying to find binary wheel")
59
+ here = os.path.dirname(__file__)
60
+ # eccodes libs are actually in eccodes dir, not gribapi dir
61
+ here = os.path.abspath(os.path.join(here, os.path.pardir, "eccodes"))
62
+ extension = EXTENSIONS.get(sys.platform, ".so")
63
+
64
+ for libdir in [here + ".libs", os.path.join(here, ".dylibs"), here]:
65
+ LOG.debug(f"{name} lib search: looking in {libdir}")
66
+ if not name.startswith("lib"):
67
+ libnames = ["lib" + name, name]
68
+ else:
69
+ libnames = [name, name[3:]]
70
+
71
+ if os.path.exists(libdir):
72
+ for file in os.listdir(libdir):
73
+ if file.endswith(extension):
74
+ for libname in libnames:
75
+ if libname == file.split("-")[0].split(".")[0]:
76
+ foundlib = os.path.join(libdir, file)
77
+ LOG.debug(
78
+ f"{name} lib search: returning wheel library from {foundlib}"
79
+ )
80
+ # force linking with the C++ 'glue' library
81
+ try:
82
+ from eccodes._eccodes import versions as _versions
83
+ except ImportError as e:
84
+ LOG.warn(str(e))
85
+ raise
86
+ LOG.debug(
87
+ f"{name} lib search: versions: %s", _versions()
88
+ )
89
+ return foundlib
90
+
91
+ LOG.debug(
92
+ f"{name} lib search: did not find library from wheel; try to find as separate lib"
93
+ )
94
+
95
+ # if did not find the binary wheel, or the env var is set, fall back to findlibs
96
+ import findlibs
97
+
98
+ foundlib = findlibs.find(name)
99
+ LOG.debug(f"{name} lib search: findlibs returned {foundlib}")
100
+ return foundlib
101
+
102
+
103
+ library_path = find_binary_libs("eccodes")
104
+
105
+ if library_path is None:
106
+ raise RuntimeError("Cannot find the ecCodes library")
107
+
108
+ # default encoding for ecCodes strings
109
+ ENC = "ascii"
110
+
111
+ ffi = cffi.FFI()
112
+ CDEF = pkgutil.get_data(__name__, "grib_api.h")
113
+ CDEF += pkgutil.get_data(__name__, "eccodes.h")
114
+ ffi.cdef(CDEF.decode("utf-8").replace("\r", "\n"))
115
+
116
+
117
+ lib = ffi.dlopen(library_path)
@@ -581,7 +581,7 @@ def grib_multi_append(ingribid, startsection, multigribid):
581
581
  @require(msgid=int, key=str)
582
582
  def grib_get_size(msgid, key):
583
583
  """
584
- @brief Get the size of an array key.
584
+ @brief Get the size of a key. Return 1 for scalar keys and >1 for array keys
585
585
 
586
586
  \b Examples: \ref grib_get_keys.py "grib_get_keys.py",\ref count_messages.py "count_messages.py"
587
587
 
@@ -36,6 +36,43 @@ def parse_version_from(path):
36
36
  return version_match.group(1)
37
37
 
38
38
 
39
+ # for the binary wheel
40
+ libdir = os.path.realpath("install/lib")
41
+ incdir = os.path.realpath("install/include")
42
+ libs = ["eccodes"]
43
+
44
+ if "--binary-wheel" in sys.argv:
45
+ sys.argv.remove("--binary-wheel")
46
+
47
+ # https://setuptools.pypa.io/en/latest/userguide/ext_modules.html
48
+ ext_modules = [
49
+ setuptools.Extension(
50
+ "eccodes._eccodes",
51
+ sources=["eccodes/_eccodes.cc"],
52
+ language="c++",
53
+ libraries=libs,
54
+ library_dirs=[libdir],
55
+ include_dirs=[incdir],
56
+ extra_link_args=["-Wl,-rpath," + libdir],
57
+ )
58
+ ]
59
+
60
+ def shared(directory):
61
+ result = []
62
+ for path, dirs, files in os.walk(directory):
63
+ for f in files:
64
+ result.append(os.path.join(path, f))
65
+ return result
66
+
67
+ # Paths must be relative to package directory...
68
+ shared_files = ["versions.txt"]
69
+ shared_files += [x[len("eccodes/") :] for x in shared("eccodes/copying")]
70
+
71
+ else:
72
+ ext_modules = []
73
+ shared_files = []
74
+
75
+
39
76
  install_requires = ["numpy"]
40
77
  if sys.version_info < (3, 7):
41
78
  install_requires = ["numpy<1.20"]
@@ -57,6 +94,7 @@ setuptools.setup(
57
94
  url="https://github.com/ecmwf/eccodes-python",
58
95
  packages=setuptools.find_packages(),
59
96
  include_package_data=True,
97
+ package_data={"": shared_files},
60
98
  install_requires=install_requires,
61
99
  tests_require=[
62
100
  "pytest",
@@ -78,4 +116,5 @@ setuptools.setup(
78
116
  "Programming Language :: Python :: Implementation :: PyPy",
79
117
  "Operating System :: OS Independent",
80
118
  ],
119
+ ext_modules=ext_modules,
81
120
  )
@@ -576,7 +576,8 @@ def test_grib_ecc_1007():
576
576
 
577
577
  def test_grib_set_bitmap():
578
578
  gid = eccodes.codes_grib_new_from_samples("GRIB2")
579
- missing = np.Infinity
579
+ # Note: np.Infinity was removed in the NumPy 2.0 release. Use np.inf instead
580
+ missing = np.inf
580
581
  eccodes.codes_set(gid, "bitmapPresent", 1)
581
582
  eccodes.codes_set(gid, "missingValue", missing)
582
583
  # Grid with 100 points 2 of which are missing
@@ -965,7 +966,7 @@ def test_bufr_copy_data():
965
966
  # ---------------------------------------------
966
967
  def test_grib_nearest2():
967
968
  if "codes_grib_nearest_new" not in dir(eccodes):
968
- return
969
+ pytest.skip("codes_grib_nearest_new absent")
969
970
  gid = eccodes.codes_grib_new_from_samples("gg_sfc_grib2")
970
971
  lat, lon = 40, 20
971
972
  flags = eccodes.CODES_GRIB_NEAREST_SAME_GRID | eccodes.CODES_GRIB_NEAREST_SAME_POINT
@@ -1,46 +0,0 @@
1
- #
2
- # (C) Copyright 2017- ECMWF.
3
- #
4
- # This software is licensed under the terms of the Apache Licence Version 2.0
5
- # which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6
- #
7
- # In applying this licence, ECMWF does not waive the privileges and immunities
8
- # granted to it by virtue of its status as an intergovernmental organisation nor
9
- # does it submit to any jurisdiction.
10
- #
11
-
12
- # Authors:
13
- # Alessandro Amici - B-Open - https://bopen.eu
14
- # Shahram Najm - ECMWF - https://www.ecmwf.int
15
- #
16
-
17
- from __future__ import absolute_import, division, print_function, unicode_literals
18
-
19
- import logging
20
- import pkgutil
21
-
22
- import cffi
23
-
24
- __version__ = "1.7.0"
25
-
26
- LOG = logging.getLogger(__name__)
27
-
28
- try:
29
- import ecmwflibs as findlibs
30
- except ImportError:
31
- import findlibs
32
-
33
- library_path = findlibs.find("eccodes")
34
- if library_path is None:
35
- raise RuntimeError("Cannot find the ecCodes library")
36
-
37
- # default encoding for ecCodes strings
38
- ENC = "ascii"
39
-
40
- ffi = cffi.FFI()
41
- CDEF = pkgutil.get_data(__name__, "grib_api.h")
42
- CDEF += pkgutil.get_data(__name__, "eccodes.h")
43
- ffi.cdef(CDEF.decode("utf-8").replace("\r", "\n"))
44
-
45
-
46
- lib = ffi.dlopen(library_path)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes