Compare commits

...
Sign in to create a new pull request.

13 commits

Author SHA1 Message Date
Benjamin A. Beasley
7d275864c0 Fix broken runtime pyproj dependency (fix RHBZ#2234805) 2023-08-25 11:08:56 -04:00
Benjamin A. Beasley
3a8551e706 Backport upstream PR#863 (“use only lxml for XML handling”)
- Fixes CVE-2023-27476 https://nvd.nist.gov/vuln/detail/CVE-2023-27476
- Fixes GHSA-8h9c-r582-mggc https://github.com/geopython/OWSLib/security/advisories/GHSA-8h9c-r582-mggc
- Fixes RHBZ#2176417 https://bugzilla.redhat.com/show_bug.cgi?id=2176417
2023-03-08 09:11:05 -05:00
Benjamin A. Beasley
050ce07c62 Update to 0.9.2
- Drop the Python 3 subpackage (which was never actually built as an
  update) since pyproj is not available
2023-03-08 08:52:23 -05:00
Benjamin A. Beasley
249e830c17 Convert to %autorelease and %autochangelog
[skip changelog]
2023-03-08 08:42:59 -05:00
Benjamin A. Beasley
00f04a41f2 Add dependency version bounds 2023-03-08 08:42:13 -05:00
Benjamin A. Beasley
55880a3f49 Install more text documentation files 2023-03-08 08:38:15 -05:00
Benjamin A. Beasley
5d046039a1 Switch to the GitHub source archive and run the offline tests 2023-03-08 08:36:55 -05:00
Benjamin A. Beasley
bcf8c16765 Build the Python 3 sub-package on EPEL7 2023-03-08 07:54:43 -05:00
Benjamin A. Beasley
417d4722f6 Update License to SPDX 2023-03-08 07:53:39 -05:00
Benjamin A. Beasley
962fd669cf Generally “modernize” packaging (by EPEL7 standards) 2023-03-08 07:53:39 -05:00
Dave Johansen
36ed902e1e Reverting back to 0.9.0 since 0.9.1 adds a dependency on pyproj (which isn't available and would be non-trivial to add) 2015-09-20 09:37:10 -07:00
Dave Johansen
7e9186a0eb Update to 0.9.1 (merged from master) 2015-09-06 16:35:34 -07:00
Dave Johansen
384c14733c Turn off Python 3 support in EPEL 2015-06-14 17:56:11 -07:00
5 changed files with 453 additions and 106 deletions

2
.gitignore vendored
View file

@ -6,4 +6,4 @@
/OWSLib-0.8.12.tar.gz
/OWSLib-0.8.13.tar.gz
/OWSLib-0.9.0.tar.gz
/OWSLib-0.9.1.tar.gz
/OWSLib-0.9.2.tar.gz

View file

@ -0,0 +1,232 @@
From 2f81f2b36c01b2a32e8dcf6b2c695b36b1eb0b8f Mon Sep 17 00:00:00 2001
From: Tom Kralidis <tomkralidis@gmail.com>
Date: Fri, 24 Feb 2023 10:15:35 -0500
Subject: [PATCH] use only lxml for XML handling
Backport of PR#863 (https://github.com/geopython/OWSLib/pull/863) to 0.9.2
---
owslib/etree.py | 58 ++++++++---------------------
owslib/util.py | 96 ++++++++++++++++++------------------------------
requirements.txt | 1 +
3 files changed, 52 insertions(+), 103 deletions(-)
diff --git a/owslib/etree.py b/owslib/etree.py
index b8babe8..88ae7ab 100644
--- a/owslib/etree.py
+++ b/owslib/etree.py
@@ -6,9 +6,15 @@
from __future__ import (absolute_import, division, print_function)
import six
-import inspect
-def patch_well_known_namespaces(etree_module):
+from lxml import etree
+from lxml.etree import ParseError
+ElementType = etree._Element
+
+from owslib.namespaces import Namespaces
+
+def patch_well_known_namespaces():
+ """Monkey patches lxml.etree to add some well-known namespaces."""
import warnings
from owslib.namespaces import Namespaces
@@ -17,50 +23,18 @@ def patch_well_known_namespaces(etree_module):
"""Monkey patches the etree module to add some well-known namespaces."""
try:
- register_namespace = etree_module.register_namespace
+ register_namespace = etree.register_namespace
except AttributeError:
- try:
- etree_module._namespace_map
+ etree._namespace_map
- def register_namespace(prefix, uri):
- etree_module._namespace_map[uri] = prefix
- except AttributeError:
- def register_namespace(prefix, uri):
- pass
- warnings.warn("Only 'lxml.etree' >= 2.3 and 'xml.etree.ElementTree' >= 1.3 are fully supported!")
+ def register_namespace(prefix, uri):
+ etree._namespace_map[uri] = prefix
for k, v in six.iteritems(ns.get_namespaces()):
register_namespace(k, v)
-# try to find lxml or elementtree
-try:
- from lxml import etree
- from lxml.etree import ParseError
- ElementType = etree._Element
-except ImportError:
- try:
- # Python 2.x/3.x with ElementTree included
- import xml.etree.ElementTree as etree
-
- try:
- from xml.etree.ElementTree import ParseError
- except ImportError:
- from xml.parsers.expat import ExpatError as ParseError
-
- if hasattr(etree, 'Element') and inspect.isclass(etree.Element):
- # python 3.4, 3.3, 2.7
- ElementType = etree.Element
- else:
- # python 2.6
- ElementType = etree._ElementInterface
-
- except ImportError:
- try:
- # Python < 2.5 with ElementTree installed
- import elementtree.ElementTree as etree
- ParseError = StandardError # i can't find a ParseError related item in elementtree docs!
- ElementType = etree.Element
- except ImportError:
- raise RuntimeError('You need either lxml or ElementTree to use OWSLib!')
+ etree.set_default_parser(
+ parser=etree.XMLParser(resolve_entities=False)
+ )
-patch_well_known_namespaces(etree)
+patch_well_known_namespaces()
diff --git a/owslib/util.py b/owslib/util.py
index 22bcaa7..51ce6d0 100644
--- a/owslib/util.py
+++ b/owslib/util.py
@@ -239,11 +239,8 @@ def nspath_eval(xpath, namespaces):
def cleanup_namespaces(element):
""" Remove unused namespaces from an element """
- if etree.__name__ == 'lxml.etree':
- etree.cleanup_namespaces(element)
- return element
- else:
- return etree.fromstring(etree.tostring(element))
+ etree.cleanup_namespaces(element)
+ return element
def add_namespaces(root, ns_keys):
@@ -254,35 +251,34 @@ def add_namespaces(root, ns_keys):
ns_keys = [(x, namespaces.get_namespace(x)) for x in ns_keys]
- if etree.__name__ != 'lxml.etree':
- # We can just add more namespaces when not using lxml.
- # We can't re-add an existing namespaces. Get a list of current
- # namespaces in use
- existing_namespaces = set()
- for elem in root.getiterator():
- if elem.tag[0] == "{":
- uri, tag = elem.tag[1:].split("}")
- existing_namespaces.add(namespaces.get_namespace_from_url(uri))
- for key, link in ns_keys:
- if link is not None and key not in existing_namespaces:
- root.set("xmlns:%s" % key, link)
- return root
- else:
- # lxml does not support setting xmlns attributes
- # Update the elements nsmap with new namespaces
- new_map = root.nsmap
- for key, link in ns_keys:
- if link is not None:
- new_map[key] = link
- # Recreate the root element with updated nsmap
- new_root = etree.Element(root.tag, nsmap=new_map)
- # Carry over attributes
- for a, v in list(root.items()):
- new_root.set(a, v)
- # Carry over children
- for child in root:
- new_root.append(deepcopy(child))
- return new_root
+ # lxml does not support setting xmlns attributes
+ # Update the elements nsmap with new namespaces
+ new_map = root.nsmap
+ for key, link in ns_keys:
+ if link is not None:
+ new_map[key] = link
+ # Recreate the root element with updated nsmap
+ new_root = etree.Element(root.tag, nsmap=new_map)
+ # Carry over attributes
+ for a, v in list(root.items()):
+ new_root.set(a, v)
+ # Carry over children
+ for child in root:
+ new_root.append(deepcopy(child))
+ return new_root
+
+ # We can just add more namespaces when not using lxml.
+ # We can't re-add an existing namespaces. Get a list of current
+ # namespaces in use
+ existing_namespaces = set()
+ for elem in root.iter():
+ if elem.tag[0] == "{":
+ uri, tag = elem.tag[1:].split("}")
+ existing_namespaces.add(namespaces.get_namespace_from_url(uri))
+ for key, link in ns_keys:
+ if link is not None and key not in existing_namespaces:
+ root.set("xmlns:%s" % key, link)
+ return root
def getXMLInteger(elem, tag):
@@ -401,20 +397,13 @@ def element_to_string(element, encoding=None, xml_declaration=False):
if encoding is None:
encoding = "ISO-8859-1"
- if etree.__name__ == 'lxml.etree':
- if xml_declaration:
- if encoding in ['unicode', 'utf-8']:
- output = '<?xml version="1.0" encoding="utf-8" standalone="no"?>\n%s' % \
- etree.tostring(element, encoding='unicode')
- else:
- output = etree.tostring(element, encoding=encoding, xml_declaration=True)
+ if xml_declaration:
+ if encoding in ['unicode', 'utf-8']:
+ output = '<?xml version="1.0" encoding="utf-8" standalone="no"?>\n%s' % \
+ etree.tostring(element, encoding='unicode')
else:
- output = etree.tostring(element)
+ output = etree.tostring(element, encoding=encoding, xml_declaration=True)
else:
- if xml_declaration:
- output = '<?xml version="1.0" encoding="%s" standalone="no"?>\n%s' % (encoding,
- etree.tostring(element, encoding=encoding))
- else:
output = etree.tostring(element)
return output
@@ -581,18 +570,3 @@ try: # 2.7
from collections import OrderedDict
except: # 2.6
from ordereddict import OrderedDict
-
-
-def which_etree():
- """decipher which etree library is being used by OWSLib"""
-
- which_etree = None
-
- if 'lxml' in etree.__file__:
- which_etree = 'lxml.etree'
- elif 'xml/etree' in etree.__file__:
- which_etree = 'xml.etree'
- elif 'elementree' in etree.__file__:
- which_etree = 'elementtree.ElementTree'
-
- return which_etree
diff --git a/requirements.txt b/requirements.txt
index 7689a61..10ad5db 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,4 @@
+lxml
python-dateutil>=1.5
pytz
requests>=1.0
--
2.39.2

38
changelog Normal file
View file

@ -0,0 +1,38 @@
* Wed Mar 08 2023 Benjamin A. Beasley <code@musicinmybrain.net> - 0.9.0-2
- Generally “modernize” packaging (by EPEL7 standards)
- Update License to SPDX
- Build the Python 3 sub-package on EPEL7
- Switch to the GitHub source archive and run the offline tests
- Install more text documentation files
- Add dependency version bounds
* Sat Jun 13 2015 Volker Fröhlich <volker27@gmx.at> - 0.9.0-1
- New upstream release
- Add Python 3 sub-package
* Sat Feb 14 2015 Volker Fröhlich <volker27@gmx.at> - 0.8.13-1
- New upstream release
* Tue Dec 23 2014 Volker Fröhlich <volker27@gmx.at> - 0.8.12-1
- New upstream release
* Wed Dec 17 2014 Volker Fröhlich <volker27@gmx.at> - 0.8.11-1
- New upstream release
* Mon Oct 13 2014 Volker Fröhlich <volker27@gmx.at> - 0.8.10-1
- New upstream release
* Wed Sep 24 2014 Volker Fröhlich <volker27@gmx.at> - 0.8.9-1
- New upstream release
* Mon Jul 7 2014 Volker Fröhlich <volker27@gmx.at> - 0.8.8-1
- New upstream release
* Wed Jul 2 2014 Volker Fröhlich <volker27@gmx.at> - 0.8.7-3
- Changed package summary
* Tue Jul 1 2014 Volker Fröhlich <volker27@gmx.at> - 0.8.7-2
- Correct BR python-setuptools-devel to python-setuptools
* Mon Jun 30 2014 Volker Fröhlich <volker27@gmx.at> - 0.8.7-1
- Initial package for Fedora

View file

@ -1,131 +1,208 @@
# Works with either ElementTree or python-lxml
%global modname OWSLib
%global with_python3 1
Name: python-%{modname}
Version: 0.9.1
Release: 1%{?dist}
# No pyproj for Python 3 in EPEL7
%bcond_with python3
Name: python-OWSLib
Version: 0.9.2
Release: %autorelease
Summary: Client library for OGC web services
License: BSD
License: BSD-3-Clause
URL: http://geopython.github.io/OWSLib
Source0: http://pypi.python.org/packages/source/O/%{modname}/%{modname}-%{version}.tar.gz
%global forgeurl https://github.com/geopython/OWSLib
Source0: %{forgeurl}/archive/%{version}/OWSLib-%{version}.tar.gz
# use only lxml for XML handling
# Backport of PR#863 (https://github.com/geopython/OWSLib/pull/863) to 0.9.2
# Fixes: CVE-2023-27476 https://nvd.nist.gov/vuln/detail/CVE-2023-27476
# GHSA-8h9c-r582-mggc https://github.com/geopython/OWSLib/security/advisories/GHSA-8h9c-r582-mggc
# RHBZ#2176417 https://bugzilla.redhat.com/show_bug.cgi?id=2176417
Patch0: 0001-use-only-lxml-for-XML-handling.patch
BuildArch: noarch
%global common_description %{expand:
Package for client programming with Open Geospatial Consortium (OGC) web
service (hence OWS) interface standards, and their related content models.}
%description %{common_description}
%package -n python2-OWSLib
Summary: %{summary}
%{?python_provide:%python_provide python2-OWSLib}
BuildRequires: python2-devel
BuildRequires: python-setuptools
Requires: python-dateutil
Requires: python-requests
Requires: pytz
BuildRequires: python2-setuptools
BuildRequires: python2-pytest
%if 0%{?with_python3}
BuildRequires: python3-devel
BuildRequires: python3-setuptools
%endif # if with_python3
BuildRequires: python2-dateutil >= 1.5
BuildRequires: python2-requests >= 1.0
BuildRequires: python2-pytz
BuildRequires: pyproj
BuildRequires: python-lxml
%description
Package for client programming with Open Geospatial Consortium (OGC) web
service (hence OWS) interface standards, and their related content models.
Requires: python2-dateutil >= 1.5
Requires: python2-requests >= 1.0
Requires: python2-pytz
Requires: pyproj
Requires: python-lxml
%if 0%{?with_python3}
%package -n python3-OWSLib
Summary: Client library for OGC web services
%description -n python2-OWSLib %{common_description}
Requires: python3-dateutil
Requires: python3-requests
Requires: python3-pytz
%description -n python3-OWSLib
Package for client programming with Open Geospatial Consortium (OGC) web
service (hence OWS) interface standards, and their related content models.
%endif # if with_python3
%if %{with python3}
%package -n python%{python3_pkgversion}-OWSLib
Summary: %{summary}
%{?python_provide:%python_provide python%{python3_pkgversion}-OWSLib}
BuildRequires: python%{python3_pkgversion}-devel
BuildRequires: python%{python3_pkgversion}-setuptools
BuildRequires: python%{python3_pkgversion}-pytest
BuildRequires: python%{python3_pkgversion}-dateutil >= 1.5
BuildRequires: python%{python3_pkgversion}-requests >= 1.0
BuildRequires: python%{python3_pkgversion}-pytz
BuildRequires: python%{python3_pkgversion}-pyproj
BuildRequires: python%{python3_pkgversion}-lxml
Requires: python%{python3_pkgversion}-dateutil >= 1.5
Requires: python%{python3_pkgversion}-requests >= 1.0
Requires: python%{python3_pkgversion}-pytz
Requires: python%{python3_pkgversion}-pyproj
Requires: python%{python3_pkgversion}-lxml
%description -n python%{python3_pkgversion}-OWSLib %{common_description}
%endif
%prep
%setup -qc -n %{modname}-%{version}
rm -rf %{modname}-%{version}/%{modname}.egg-info
mv %{modname}-%{version} python2
%autosetup -n OWSLib-%{version} -p1
rm -rf OWSLib.egg-info
%if 0%{?with_python3}
cp -a python2 python3
find python3 -name '*.py' | xargs sed -i '1s|^#!python|#!%{__python3}|'
%endif # with_python3
# Remove shebangs from non-script sources. The find-then-modify pattern
# preserves mtimes on sources that did not need to be modified.
find 'owslib' -type f -name '*.py' \
-exec gawk '/^#!/ { print FILENAME }; { nextfile }' '{}' '+' |
xargs -r sed -r -i '1{/^#!/d}'
find python2 -name '*.py' | xargs sed -i '1s|^#!python|#!%{__python2}|'
pushd python2
cp -pr LICENSE.txt README.txt CHANGES.txt CREDITS.txt ../
popd
# https://docs.fedoraproject.org/en-US/packaging-guidelines/Python/#_linters
sed -r -i 's/--cov[^[:blank:]=]*([=[:blank:]][^-][^[:blank:]]+)?//g' tox.ini
%build
pushd python2
%{__python2} setup.py build
popd
%if 0%{?with_python3}
pushd python3
%{__python3} setup.py build
popd
%endif # if with_python3
%py2_build
%if %{with python3}
%py3_build
%endif
%install
pushd python2
%{__python2} setup.py install --skip-build --root %{buildroot}
popd
%if 0%{?with_python3}
pushd python3
%{__python3} setup.py install --skip-build --root %{buildroot}
popd
%endif # if with_python3
%py2_install
%if %{with python3}
%py3_install
%endif
%files
%doc LICENSE.txt README.txt CHANGES.txt CREDITS.txt
%{python_sitelib}/owslib
%{python_sitelib}/%{modname}-%{version}-py*.egg-info
%check
# Otherwise, pytest finds the package twice in the Python path and complains.
rm -rf owslib
# In recent versions, there is a convenient “online” mark for deselecting tests
# that require Internet access, but we still have to manually deselect doctests
# that try to make network requests.
k="${k-}${k+ and }not (wms_geoserver_mass_gis and txt)"
k="${k-}${k+ and }not (wfs_MapServerWFSFeature and txt)"
k="${k-}${k+ and }not (wfs_MapServerWFSCapabilities and txt)"
k="${k-}${k+ and }not (wfs2_storedqueries and txt)"
k="${k-}${k+ and }not (wfs1_generic and txt)"
k="${k-}${k+ and }not (wcs_thredds and txt)"
k="${k-}${k+ and }not (test_wmts_example_informatievlaanderen and txt)"
# These require network access, and would be covered by the “online” mark:
k="${k-}${k+ and }not (WebMapService and getmap)"
k="${k-}${k+ and }not (WebMapTileService and buildTileRequest)"
k="${k-}${k+ and }not (WebMapTileService and gettile)"
k="${k-}${k+ and }not (csw_gdp and txt)"
k="${k-}${k+ and }not (csw_geonetwork and txt)"
k="${k-}${k+ and }not (csw_geoserver and txt)"
k="${k-}${k+ and }not (csw_linz and txt)"
k="${k-}${k+ and }not (csw_ngdc and txt)"
k="${k-}${k+ and }not (csw_nlr and txt)"
k="${k-}${k+ and }not (csw_pycsw and txt)"
k="${k-}${k+ and }not (csw_pycsw_skip_caps and txt)"
k="${k-}${k+ and }not (csw_skgeodsy and txt)"
k="${k-}${k+ and }not (csw_uuid_constrain and txt)"
k="${k-}${k+ and }not (ows_interfaces and txt)"
k="${k-}${k+ and }not (sos_10_ndbc_getobservation and txt)"
k="${k-}${k+ and }not (tms and txt)"
k="${k-}${k+ and }not (wcs_idee and txt)"
k="${k-}${k+ and }not (wfs_USDASSURGO and txt)"
k="${k-}${k+ and }not (wms_JPLCapabilities and txt)"
k="${k-}${k+ and }not (wms_getfeatureinfo and txt)"
k="${k-}${k+ and }not (wmts and txt)"
k="${k-}${k+ and }not (wps_execute and txt)"
k="${k-}${k+ and }not (wps_execute_invalid_request and txt)"
# Unknown problem—check if it is fixed in a later version:
k="${k-}${k+ and } not (TestOffline and test_wfs_110_remotemd_parse_all)"
k="${k-}${k+ and } not (TestOffline and test_wfs_110_remotemd_parse_single)"
k="${k-}${k+ and } not (TestOffline and test_wfs_200_remotemd_parse_single)"
k="${k-}${k+ and } not (TestOffline and test_wms_130_remotemd_parse_all)"
k="${k-}${k+ and } not (TestOffline and test_wms_130_remotemd_parse_single)"
# ____________ [doctest] tests/doctests/wms_GeoServerCapabilities.txt ____________
# 062 >>> x = wms['opengeo:poi'].styles
# 063 >>> x == {'point': {'legend': 'http://localhost:8080/geoserver/wms?request=GetLegendGraphic&format=image%2Fpng&width=20&height=20&layer=poi', 'title': 'A boring default style'}}
# 064 True
# 065
# 066 Test nested layer
# 067
# 068 >>> wms['parent_layer'].title
# 069 'Parent Layer'
# 070
# 071 >>> wms['parent_layer'].queryable
# Expected:
# 1
# Got:
# 0
k="${k-}${k+ and } not (wms_GeoServerCapabilities and txt)"
PYTHONPATH='%{buildroot}%{python2_sitelib}' PYTHONDONTWRITEBYTECODE=1 \
%{python2} -m pytest -m 'not online' -k "${k-}"
%if %{with python3}
PYTHONPATH='%{buildroot}%{python3_sitelib}' PYTHONDONTWRITEBYTECODE=1 \
%{python3} -m pytest -m 'not online' -k "${k-}"
%endif
%files -n python2-OWSLib
%license LICENSE.txt
%doc CHANGES.txt
%doc CREDITS.txt
%doc FAQ.txt
%doc HISTORY.txt
%doc README.txt
%{python2_sitelib}/owslib/
%{python2_sitelib}/OWSLib-%{version}-py%{python2_version}.egg-info
%if %{with python3}
%files -n python%{python3_pkgversion}-OWSLib
%license LICENSE.txt
%doc CHANGES.txt
%doc CREDITS.txt
%doc FAQ.txt
%doc HISTORY.txt
%doc README.txt
%{python3_sitelib}/owslib/
%{python3_sitelib}/OWSLib-%{version}-py%{python3_version}.egg-info
%endif
%if 0%{?with_python3}
%files -n python3-OWSLib
%doc LICENSE.txt README.txt CHANGES.txt CREDITS.txt
%{python3_sitelib}/owslib
%{python3_sitelib}/%{modname}-%{version}-py*.egg-info
%endif # if with_python3
%changelog
* Sun Sep 6 2015 Volker Fröhlich <volker27@gmx.at> - 0.9.1-1
- New upstream release
* Thu Jun 18 2015 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.9.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild
* Sat Jun 13 2015 Volker Fröhlich <volker27@gmx.at> - 0.9.0-1
- New upstream release
- Add Python 3 sub-package
* Sat Feb 14 2015 Volker Fröhlich <volker27@gmx.at> - 0.8.13-1
- New upstream release
* Tue Dec 23 2014 Volker Fröhlich <volker27@gmx.at> - 0.8.12-1
- New upstream release
* Wed Dec 17 2014 Volker Fröhlich <volker27@gmx.at> - 0.8.11-1
- New upstream release
* Mon Oct 13 2014 Volker Fröhlich <volker27@gmx.at> - 0.8.10-1
- New upstream release
* Wed Sep 24 2014 Volker Fröhlich <volker27@gmx.at> - 0.8.9-1
- New upstream release
* Mon Jul 7 2014 Volker Fröhlich <volker27@gmx.at> - 0.8.8-1
- New upstream release
* Wed Jul 2 2014 Volker Fröhlich <volker27@gmx.at> - 0.8.7-3
- Changed package summary
* Tue Jul 1 2014 Volker Fröhlich <volker27@gmx.at> - 0.8.7-2
- Correct BR python-setuptools-devel to python-setuptools
* Mon Jun 30 2014 Volker Fröhlich <volker27@gmx.at> - 0.8.7-1
- Initial package for Fedora
%autochangelog

View file

@ -1 +1 @@
9ca33a5815d07ae8c97dfa3747118d2c OWSLib-0.9.1.tar.gz
SHA512 (OWSLib-0.9.2.tar.gz) = 1818299d702053b344edd435417785c8dd1c4d811a8bff7919c04624cf62a9324c856604965706f0416bea827dab3e5650b1f1cf6730b1b424535673f90e4cf0