diff --git a/Makefile b/Makefile index a775e4d..9549ac1 100644 --- a/Makefile +++ b/Makefile @@ -30,6 +30,9 @@ build-dep-fed: test: copyright pylint unittest +reformat: + yapf --parallel --recursive --in-place tests/ rpm_s3_mirror/ + .PHONY: copyright copyright: $(eval MISSING_COPYRIGHT := $(shell git ls-files "*.py" | xargs grep -EL "Copyright \(c\) 20.* Aiven|Aiven license OK")) diff --git a/rpm_s3_mirror/repository.py b/rpm_s3_mirror/repository.py index 3af1c67..7f61768 100644 --- a/rpm_s3_mirror/repository.py +++ b/rpm_s3_mirror/repository.py @@ -131,8 +131,7 @@ def has_updates(self, since: datetime) -> bool: def parse_metadata(self) -> Metadata: response = self._req(self.session.get, "repodata/repomd.xml") - xml = safe_parse_xml(response.content) - repodata = self.parse_repomd(xml) + repodata = self.parse_repomd(xml=response.content) package_list = self._extract_package_list(primary=repodata["primary"]) return Metadata(package_list=package_list, repodata=repodata, base_url=self.base_url) @@ -143,7 +142,8 @@ def _extract_package_list(self, primary: RepodataSection) -> PackageList: with gzip.open(local_path) as f: return PackageList(base_url=self.base_url, packages_xml=f.read()) - def parse_repomd(self, xml: Element) -> Dict[str, RepodataSection]: + def parse_repomd(self, xml: bytes) -> Dict[str, RepodataSection]: + xml = safe_parse_xml(xml) sections = {} for data_element in xml.findall(f"repo:data", namespaces=namespaces): section_type = data_element.attrib["type"] diff --git a/rpm_s3_mirror/statsd.py b/rpm_s3_mirror/statsd.py index ff9ad17..1922563 100644 --- a/rpm_s3_mirror/statsd.py +++ b/rpm_s3_mirror/statsd.py @@ -1,5 +1,4 @@ # Copyright (c) 2020 Aiven, Helsinki, Finland. https://aiven.io/ - """ StatsD client diff --git a/tests/conftest.py b/tests/conftest.py index 38d34be..7614b94 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,9 +4,28 @@ import pytest -@pytest.fixture(name="test_package_list_xml") -def test_package_list_xml(): +def load_resource_xml(filename): root_dir = os.path.dirname(os.path.abspath(__file__)) - package_xml_path = os.path.join(root_dir, "resources", "primary.xml") + package_xml_path = os.path.join(root_dir, "resources", filename) with open(package_xml_path, "rb") as f: return f.read() + + +PACKAGE_XML = load_resource_xml(filename="primary.xml") +PACKAGE_CHANGED_XML = load_resource_xml(filename="primary-one-changed.xml") +REPOMD_XML = load_resource_xml(filename="repomd.xml") + + +@pytest.fixture(name="package_list_xml") +def package_list_xml(): + return PACKAGE_XML + + +@pytest.fixture(name="package_list_changed_xml") +def package_list_changed_xml(): + return PACKAGE_CHANGED_XML + + +@pytest.fixture(name="repomd_xml") +def repomd_xml(): + return REPOMD_XML diff --git a/tests/resources/primary-one-changed.xml b/tests/resources/primary-one-changed.xml new file mode 100644 index 0000000..4863af0 --- /dev/null +++ b/tests/resources/primary-one-changed.xml @@ -0,0 +1,931 @@ + + + GMT + i686 + + e045c5a0b1241058376f0dac30baceb07fbd2765e2fc0706d87121f788bf4b8 + Generic Mapping Tools + GMT is an open source collection of ~60 tools for manipulating geographic and +Cartesian data sets (including filtering, trend fitting, gridding, projecting, +etc.) and producing Encapsulated PostScript File (EPS) illustrations ranging +from simple x-y plots via contour maps to artificially illuminated surfaces +and 3-D perspective views. GMT supports ~30 map projections and transforma- +tions and comes with support data such as coastlines, rivers, and political +boundaries. + +GMT is developed and maintained by Paul Wessel and Walter H. F. Smith with +help from a global set of volunteers, and is supported by the National +Science Foundation. + +NOTE: Specific executables that conflict with other Fedora packages have been +removed. These functions can still be accessed via the GMT wrapper script +with: GMT <function> [args] + Fedora Project + https://www.generic-mapping-tools.org/ + + + GMT-doc + noarch + + 4c0139b19b457bff1f0307ad682fa8908e476569115ed8cced5ece7d27aeca1b + Documentation for GMT + The GMT-doc package provides the documentation for the GMT (Generic +Mapping Tools) package. + Fedora Project + https://www.generic-mapping-tools.org/ + + + GraphicsMagick-c++ + i686 + + 784424a83f98769749aede05e2f7bda122cb5600b3443cfceb9f1d83b17ae12c + GraphicsMagick Magick++ library (C++ bindings) + This package contains the GraphicsMagick++ library, a C++ binding to the +GraphicsMagick graphics manipulation library. + +Install GraphicsMagick-c++ if you want to use any applications that use +GraphicsMagick++. + Fedora Project + http://www.graphicsmagick.org/ + + + GraphicsMagick-devel + i686 + + f8d8829a4e98d19dedf755f0ff0b5b499dcd1bf0d52056da54eb5b77638ba3c4 + Libraries and header files for GraphicsMagick app development + GraphicsMagick-devel contains the Libraries and header files you'll +need to develop GraphicsMagick applications. GraphicsMagick is an image +manipulation program. + +If you want to create applications that will use GraphicsMagick code or +APIs, you need to install GraphicsMagick-devel as well as GraphicsMagick. +You do not need to install it if you just want to use GraphicsMagick, +however. + Fedora Project + http://www.graphicsmagick.org/ + + + ImageMagick + i686 + + 880e700da36911f0c008ed73082fdedf01ee1b771688e883f3565921cd2f4b6f + An X application for displaying and manipulating images + ImageMagick is an image display and manipulation tool for the X +Window System. ImageMagick can read and write JPEG, TIFF, PNM, GIF, +and Photo CD image formats. It can resize, rotate, sharpen, color +reduce, or add special effects to an image, and when finished you can +either save the completed work in the original format or a different +one. ImageMagick also includes command line programs for creating +animated or transparent .gifs, creating composite images, creating +thumbnail images, and more. + +ImageMagick is one of your choices if you need a program to manipulate +and display images. If you want to develop your own applications +which use ImageMagick code or APIs, you need to install +ImageMagick-devel as well. + Fedora Project + http://www.imagemagick.org/ + + + ImageMagick-c++-devel + i686 + + 9c22525ce337817559595aae5a6d5b9d91ae3c6405fa26ec42e875e43d2b7063 + C++ bindings for the ImageMagick library + ImageMagick-devel contains the static libraries and header files you'll +need to develop ImageMagick applications using the Magick++ C++ bindings. +ImageMagick is an image manipulation program. + +If you want to create applications that will use Magick++ code +or APIs, you'll need to install ImageMagick-c++-devel, ImageMagick-devel and +ImageMagick. +You don't need to install it if you just want to use ImageMagick, or if you +want to develop/compile applications using the ImageMagick C interface, +however. + Fedora Project + http://www.imagemagick.org/ + + + ImageMagick-devel + i686 + + e802d9d12bb6cc8ffe06589c20b9fb44f458fb26b6119aeeb2fc8c13a5f98658 + Library links and header files for ImageMagick app development + ImageMagick-devel contains the library links and header files you'll +need to develop ImageMagick applications. ImageMagick is an image +manipulation program. + +If you want to create applications that will use ImageMagick code or +APIs, you need to install ImageMagick-devel as well as ImageMagick. +You do not need to install it if you just want to use ImageMagick, +however. + Fedora Project + http://www.imagemagick.org/ + + + InsightToolkit-vtk-devel + i686 + + 307153dada4114e189f73dc40882eae16f7bb543631948f7697348aebfd038be + Libraries and header files for development of ITK-VTK bridge + Libraries and header files for development of ITK-VTK bridge + Fedora Project + https://www.itk.org/ + + + PackageKit-cron + x86_64 + + c9d736ccabfe4fe3d2a7daf2c5430bf146732a701e74e32c0882e531b7a0c65e + Cron job and related utilities for PackageKit + Crontab and utilities for running PackageKit as a cron job. + Fedora Project + http://www.freedesktop.org/software/PackageKit/ + + + R-R.devices + noarch + + aba6e8ab8b05f49c7b8ecf9fd94c89c73be88e90a5f1bf91bd3107a816444bb6 + Unified Handling of Graphics Devices + Functions for creating plots and image files in a unified way regardless of +output format (EPS, PDF, PNG, SVG, TIFF, WMF, etc.). Default device options as +well as scales and aspect ratios are controlled in a uniform way across all +device types. Switching output format requires minimal changes in code. This +package is ideal for large-scale batch processing, because it will never leave +open graphics devices or incomplete image files behind, even on errors or user +interrupts. + Fedora Project + https://CRAN.R-project.org/package=R.devices + + + R-R.rsp + noarch + + 5479db59076be1f7c660059a011d5afce42dc2e351838b3346ae8d1ce3250d78 + Dynamic Generation of Scientific Reports + The RSP markup language makes any text-based document come alive. RSP provides +a powerful markup for controlling the content and output of LaTeX, HTML, +Markdown, AsciiDoc, Sweave and knitr documents (and more), e.g. 'Today's date +is <%=Sys.Date()%>'. Contrary to many other literate programming languages, +with RSP it is straightforward to loop over mixtures of code and text sections, +e.g. in month-by-month summaries. RSP has also several preprocessing +directives for incorporating static and dynamic contents of external files +(local or online) among other things. Functions rstring() and rcat() make it +easy to process RSP strings, rsource() sources an RSP file as it was an R +script, while rfile() compiles it (even online) into its final output format, +e.g. rfile('report.tex.rsp') generates 'report.pdf' and rfile('report.md.rsp') +generates 'report.html'. RSP is ideal for self-contained scientific reports +and R package vignettes. It's easy to use - if you know how to write an R +script, you'll be up and running within minutes. + Fedora Project + https://CRAN.R-project.org/package=R.rsp + + + R-RInside + x86_64 + + 761c0f02a04b17695f1b24d8f19f816803cf8729eb811c7899504a0f0f9e5b1a + C++ Classes to Embed R in C++ (and C) Applications + The RInside packages makes it easier to have "R inside" your C++ +application by providing a C++ wrapper class providing the R +interpreter. + Fedora Project + https://cran.r-project.org/package=RInside + + + R-RInside-examples + x86_64 + + 159e3bfeb065bc5875eaf7b034bcfea0f3cc0228e61afa616c3a695b4a003453 + RInside Examples + Numerous examples are provided in the nine sub-directories of the +examples directory of the installed package: standard, mpi (for +parallel computing), qt (showing how to embed RInside inside a Qt GUI +application), wt (showing how to build a "web-application" using the +Wt toolkit), armadillo (for RInside use with RcppArmadillo), eigen +(for RInside use with RcppEigen) and 'c_interface' for a basic C +interface and 'Ruby' illustration. + Fedora Project + https://cran.r-project.org/package=RInside + + + R-XVector-devel + i686 + + 77ad6cd60e026dbf3cf5c106091bbf7016f791bcb8d4c4e5718b0bb5b94673fe + Development files for R-XVector + Development files for R-XVector. + Fedora Project + http://www.bioconductor.org/packages/release/bioc/html/XVector.html + + + R-backports + x86_64 + + 09dae965475d8be80a958ddee560eecf2e0c98333443eccc84a66938afb56667 + Reimplementations of Functions Introduced Since R-3.0.0 + Functions introduced or changed since R v3.0.0 are re-implemented in this +package. The backports are conditionally exported in order to let R resolve +the function name to either the implemented backport, or the respective +base version, if available. Package developers can make use of new +functions or arguments by selectively importing specific backports to +support older installations. + Fedora Project + https://CRAN.R-project.org/package=backports + + + R-callr + noarch + + be758223d0078ea2da7bfb7fc0fac3bf465da52b657a4e9fd3129d04d241a5f6 + Call R from R + It is sometimes useful to perform a computation in a separate R process, +without affecting the current R process at all. This packages does exactly +that. + Fedora Project + https://CRAN.R-project.org/package=callr + + + R-cli + noarch + + d3d3a4751f51a4eb6aba37dd1631f9471418ec4dc7f247cf05e09150ce1359ae + Helpers for Developing Command Line Interfaces + A suite of tools to build attractive command line interfaces ('CLIs'), from +semantic elements: headings, lists, alerts, paragraphs, etc. Supports custom +themes via a 'CSS'-like language. It also contains a number of lower level +'CLI' elements: rules, boxes, trees, and 'Unicode' symbols with 'ASCII' +alternatives. It integrates with the 'crayon' package to support 'ANSI' +terminal colors. + Fedora Project + https://CRAN.R-project.org/package=cli + + + R-curl + x86_64 + + 826f4de1836c0c9c1664a773fce4d694bd6adaeaf9edd7ff684468187333125c + A Modern and Flexible Web Client for R + The curl() and curl_download() functions provide highly configurable drop-in +replacements for base url() and download.file() with better performance, +support for encryption (https, ftps), gzip compression, authentication, and +other 'libcurl' goodies. The core of the package implements a framework for +performing fully customized requests where data can be processed either in +memory, on disk, or streaming via the callback or connection interfaces. Some +knowledge of 'libcurl' is recommended; for a more-user-friendly web client see +the 'httr' package which builds on this package with http specific tools and +logic. + Fedora Project + https://CRAN.R-project.org/package=curl + + + R-cyclocomp + noarch + + eb4574d3fe68d8bff8ee663bc6ae7d4d688fe8e63d9b7546bbeace948458bae5 + Cyclomatic Complexity of R Code + Cyclomatic complexity is a software metric (measurement), used to indicate +the complexity of a program. It is a quantitative measure of the number of +linearly independent paths through a program's source code. It was +developed by Thomas J. McCabe, Sr. in 1976. + Fedora Project + https://CRAN.R-project.org/package=cyclocomp + + + R-deldir + x86_64 + + 6d9c130810333486a3b6916bb483a1e2b117779aa327b0a84a9891199dad43cf + Delaunay Triangulation and Dirichlet (Voronoi) Tessellation + Calculates the Delaunay triangulation and the Dirichlet or Voronoi +tessellation (with respect to the entire plane) of a planar point set. +Plots triangulations and tessellations in various ways. Clips +tessellations to sub-windows. Calculates perimeters of tessellations. +Summarises information about the tiles of the tessellation. + Fedora Project + https://CRAN.R-project.org/package=deldir + + diff --git a/tests/resources/repomd.xml b/tests/resources/repomd.xml new file mode 100644 index 0000000..1031106 --- /dev/null +++ b/tests/resources/repomd.xml @@ -0,0 +1,141 @@ + + + 1587867572 + + df0a31f7ab547ef2231eaedac2c00280ea4512dfa697da4c6f21c2eeee2ca653 + 1c28ec6bbd36dc37cda36d84883d5e26bf3260042fa9c39bed350cd70110456f + + 1587867173 + 5731631 + 54911950 + + + 6957f0f984e4bf67998529227f9b790efa58deb3c1699e4c4852c4dbff04fc59 + aec1d9e752ed437beebe3374c6bb74f7a2fb53ce0fbd571637f72ee52c1b1008 + + 1587867173 + 20984591 + 289759424 + + + 36b4d77da655b84f886c2aba829d22fa05545e069f3b1d734fdc5cf5fed30648 + b3086728d0583c11218c5df1ec4a9bedac718ca8d8fdbe3c5ad6e73f2029742f + + 1587867173 + 2333594 + 36845799 + + + 9af4005c4e601da4141822c4e4eaa9deda09b5e5bc75a086c2acd101c57345ee + 9c6c6efce39d2caf0ac6cdc0c0a6988103f822c007b3d05099807509d8da8745 + + 1587867251 + 11798983 + 57327616 + 10 + + + 09f119eb1b87875eccde402ce5a813a7d3f91b5d3d03cd62c34583506a9bfa27 + d9af99bd21c66836ac672380e2dde3ba1af818c6af71ce1fa010d9bd68397ad7 + + 1587867266 + 20645183 + 132247552 + 10 + + + 2241e176091360cbb8fb8cb5fa6d7d6851f4958755a9aac606f8c507352eff3c + 34efa52a2c52d5926d9cd1e4693df457950f7738ea6e226cbf025590fd777f6a + + 1587867247 + 3948461 + 31543296 + 10 + + + 876b3081bbb63c4835563a448d85570fdae9eebb7d2efcb37d2d540957a8b1d3 + 1c28ec6bbd36dc37cda36d84883d5e26bf3260042fa9c39bed350cd70110456f + f5ea0837be3a675f08d9cac1e652712826bcbacd2101e867fcacb25991ff3417 + + 1587867173 + 5489353 + 54911950 + 107378 + + + 9cfa6d492833ca9c5fe7392476b1b2586dc1462025bebfd178b12017471cdbf6 + aec1d9e752ed437beebe3374c6bb74f7a2fb53ce0fbd571637f72ee52c1b1008 + 8fb32f2c88980b1e72b18561805d80be7499d2c8f18e48f6c931968b8de2f726 + + 1587867174 + 16751184 + 289759424 + 108329 + + + 3abe0789c2e0369b4432b1b25a001064d59ee9cfe6e8e3685a8dee2a5aaa2201 + b3086728d0583c11218c5df1ec4a9bedac718ca8d8fdbe3c5ad6e73f2029742f + 24f7ee220491f1925b284b8baf3185f35da3177c59baaf4408656d5e148e95d3 + + 1587867174 + 2419953 + 36845799 + 106897 + + + 9831064bb0ea0bce4c0c454053ab778481ebf87fc1cc7c9b0a393ad7b4a6a4f2 + + 1587861678 + 1772935 + + + 6ab0e9a7ad06dc195a1d003d3fa1ba6682da051d3bfb7612b6551f4246003f17 + + 1587867174 + 433529 + + + f2509a1cccdef24dc2b873bc537a4c76da2ee4cb60160c908d7410e519bdfab4 + 6ab0e9a7ad06dc195a1d003d3fa1ba6682da051d3bfb7612b6551f4246003f17 + 42d39b12b226383346b717fde7928bdb223a782c8b81376590253b66138fc54a + + 1587867273 + 477231 + 433529 + 1200 + + + c39046ec3ed2813ef94b07b3664c556f40b72ef5988872511e8e64716f1a25b7 + 32071cf6b9f5fe2053607d1f2df25cff88ebe7aba311d3f4f2de96b70975050b + + 1587867572 + 15730 + 87710 + + + 37ef7542fb5233d40749c8e3455b181c513682a840493e8f63162e34da72fd02 + 32071cf6b9f5fe2053607d1f2df25cff88ebe7aba311d3f4f2de96b70975050b + + 1587867572 + 50378 + 87710 + + + 4fc1cd2996f92d0c32f61e83c2f927f171abae4bf6e8013e58bbb012bcbec12e + 9cab081d5a7ed2c7a4a63289a9371bd0c6d7b6db20d320b6f514d8b0693faac7 + + 1587868111 + 1791440 + 36566799 + + + 9a9ac8e15d2fd91c1789ba9f6811db121f5e6916a0f3b518ca1211e6d6e02f43 + 9cab081d5a7ed2c7a4a63289a9371bd0c6d7b6db20d320b6f514d8b0693faac7 + c7e2f3a2b40566a16bba038dc24bce851bcfc5228643b579047b3707c37d360e + + 1587868112 + 2222811 + 36566799 + 11390 + + diff --git a/tests/test_package.py b/tests/test_package.py deleted file mode 100644 index 9556bb2..0000000 --- a/tests/test_package.py +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) 2020 Aiven, Helsinki, Finland. https://aiven.io/ - -from rpm_s3_mirror.repository import Package, PackageList - - -def test_package_list(test_package_list_xml): - package_list = PackageList(base_url="https://some.repo/some/path", packages_xml=test_package_list_xml) - packages = list(package_list) - assert len(package_list) > 0 - assert len(package_list) == len(packages) - assert all((isinstance(package, Package) for package in packages)) diff --git a/tests/test_repository.py b/tests/test_repository.py new file mode 100644 index 0000000..9c05a39 --- /dev/null +++ b/tests/test_repository.py @@ -0,0 +1,86 @@ +# Copyright (c) 2020 Aiven, Helsinki, Finland. https://aiven.io/ + +from rpm_s3_mirror.repository import Package, PackageList, RPMRepository + +TEST_BASE_URL = "https://some.repo/some/path" +CHANGED_PACKAGE_NAME = "GMT" + +EXPECTED_REPOMD_KEYS = [ + "primary", + "filelists", + "other", + "primary_db", + "filelists_db", + "other_db", + "primary_zck", + "filelists_zck", + "other_zck", + "group", + "group_gz", + "group_zck", + "prestodelta", + "prestodelta_zck", + "updateinfo", + "updateinfo_zck", +] + +EXPECTED_REPOMD_CHECKSUMS = { + "primary": "df0a31f7ab547ef2231eaedac2c00280ea4512dfa697da4c6f21c2eeee2ca653", + "filelists": "6957f0f984e4bf67998529227f9b790efa58deb3c1699e4c4852c4dbff04fc59", + "other": "36b4d77da655b84f886c2aba829d22fa05545e069f3b1d734fdc5cf5fed30648", + "primary_db": "9af4005c4e601da4141822c4e4eaa9deda09b5e5bc75a086c2acd101c57345ee", + "filelists_db": "09f119eb1b87875eccde402ce5a813a7d3f91b5d3d03cd62c34583506a9bfa27", + "other_db": "2241e176091360cbb8fb8cb5fa6d7d6851f4958755a9aac606f8c507352eff3c", + "primary_zck": "876b3081bbb63c4835563a448d85570fdae9eebb7d2efcb37d2d540957a8b1d3", + "filelists_zck": "9cfa6d492833ca9c5fe7392476b1b2586dc1462025bebfd178b12017471cdbf6", + "other_zck": "3abe0789c2e0369b4432b1b25a001064d59ee9cfe6e8e3685a8dee2a5aaa2201", + "group": "9831064bb0ea0bce4c0c454053ab778481ebf87fc1cc7c9b0a393ad7b4a6a4f2", + "group_gz": "6ab0e9a7ad06dc195a1d003d3fa1ba6682da051d3bfb7612b6551f4246003f17", + "group_zck": "f2509a1cccdef24dc2b873bc537a4c76da2ee4cb60160c908d7410e519bdfab4", + "prestodelta": "c39046ec3ed2813ef94b07b3664c556f40b72ef5988872511e8e64716f1a25b7", + "prestodelta_zck": "37ef7542fb5233d40749c8e3455b181c513682a840493e8f63162e34da72fd02", + "updateinfo": "4fc1cd2996f92d0c32f61e83c2f927f171abae4bf6e8013e58bbb012bcbec12e", + "updateinfo_zck": "9a9ac8e15d2fd91c1789ba9f6811db121f5e6916a0f3b518ca1211e6d6e02f43", +} + + +def test_package_list(package_list_xml): + packages = PackageList(base_url=TEST_BASE_URL, packages_xml=package_list_xml) + package_list = list(packages) + assert len(packages) > 0 + assert len(packages) == len(package_list) + assert all((isinstance(package, Package) for package in package_list)) + assert set(packages).difference(packages) == set() + + +def test_package_list_comparison(package_list_xml, package_list_changed_xml): + packages1 = PackageList(base_url=TEST_BASE_URL, packages_xml=package_list_xml) + packages2 = PackageList(base_url=TEST_BASE_URL, packages_xml=package_list_changed_xml) + + assert set(packages1).difference(set(packages1)) == set() + + changed_packages = set(packages1).difference(set(packages2)) + assert len(changed_packages) == 1 + + changed_package = list(changed_packages)[0] + assert changed_package.name == CHANGED_PACKAGE_NAME + + +def test_package_equality(package_list_xml, package_list_changed_xml): + package_list = list(PackageList(base_url=TEST_BASE_URL, packages_xml=package_list_xml)) + package1 = package_list[0] + package2 = package_list[1] + assert package1 != package2 + + package_list2 = list(PackageList(base_url=TEST_BASE_URL, packages_xml=package_list_changed_xml)) + assert package_list[1] == package_list2[1] + +def test_parse_repomd_xml(repomd_xml): + repository = RPMRepository(base_url=TEST_BASE_URL) + repomd = repository.parse_repomd(repomd_xml) + + assert list(repomd.keys()) == EXPECTED_REPOMD_KEYS + assert {k: v.checksum for k, v in repomd.items()} == EXPECTED_REPOMD_CHECKSUMS + + for repodata_section in repomd.values(): + assert all(attr is not None for attr in repodata_section._asdict().values())