Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SOS 2.0 and WaterML2.0 decoder #171

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
5d6c80e
Added a title to the service identification class.
dblodgett-usgs Aug 14, 2014
612ed10
update CSW examples
tomkralidis Jul 10, 2014
1636147
update URL
tomkralidis Jul 10, 2014
f8a9c5a
Updated credits
kalxas Jul 12, 2014
356dafb
CI_ResponsibleParty as a responsible role attribute
milokmet Jul 23, 2014
5823442
Update index.rst
tomkralidis Jul 24, 2014
2cfefb2
Added 'om' back to the list of default SOS namespaces
ict4eo Jul 30, 2014
ef49bb9
quick fix to add gmi:MI_Matadata support to csw
FuhuXia Sep 3, 2014
d54be55
update test
tomkralidis Sep 5, 2014
268bf3d
add support for Basic Authentication for CSW (#176)
tomkralidis Sep 24, 2014
2191eb2
update release version
tomkralidis Sep 24, 2014
e087c77
back to dev
tomkralidis Sep 24, 2014
7e554e6
first cut at logging instead of printing. Might need to bring back pr…
dblodgett-usgs Sep 27, 2014
3fbabd5
test logging setup from doctests
tomkralidis Sep 28, 2014
30dc489
update test logging
tomkralidis Sep 28, 2014
12313e4
route test logging to sys.stdout
tomkralidis Sep 28, 2014
0472703
test testing
tomkralidis Sep 28, 2014
460c243
refactor test logging
tomkralidis Sep 28, 2014
5c48c58
make logging level argument (default is info)
tomkralidis Sep 28, 2014
40229c7
Ignore comment tags when parsing WFS metadata.
naavis Sep 29, 2014
e6b8941
Pass encoded_request as parameter to urlopen to make proper url.
naavis Sep 29, 2014
bc8e180
Update LICENSE.txt
johanvdw Sep 30, 2014
9fd7ec2
fix bad URL being sent to CSW GetRecords #187)
tomkralidis Oct 1, 2014
d0dc95f
Adds clients specified timeouts to SOS requests
lukecampbell Oct 4, 2014
6169a82
Adds client specified timeouts to SOS 2.0
lukecampbell Oct 13, 2014
09d27e0
update release version
tomkralidis Oct 13, 2014
a267c90
back to dev
tomkralidis Oct 13, 2014
9b60980
safeguard doc builds
tomkralidis Oct 13, 2014
84415e4
Fix vendor kwarg handling
rhattersley Oct 28, 2014
4032158
Add vendor-kwargs to WMTS constructor.
rhattersley Oct 28, 2014
cdb41db
PEP 8 driven changes to wmts.py.
rhattersley Oct 29, 2014
35c4110
fix WFS tests
tomkralidis Oct 29, 2014
272dc9b
fix WFS tests
tomkralidis Oct 29, 2014
ddcd777
update WFS test
tomkralidis Oct 29, 2014
18e77bc
update WFS test
tomkralidis Oct 29, 2014
3ac47fe
update WFS test
tomkralidis Oct 29, 2014
1a62bf4
update WFS test
tomkralidis Oct 29, 2014
4fc0bc9
some wms servers lack a scalehint max attribute
SiggyF Nov 7, 2014
4025739
update failing tests
tomkralidis Nov 8, 2014
2617965
Update __init__.py
jachym Nov 12, 2014
a8e58f2
Some basic SOS2.0 calls
peterataylor Jul 9, 2014
fa677d6
SOS __getitem__ to use id not name
Dec 4, 2014
38b31b5
Additions to decode get_observation responses from SOS2.0. Adding
peterataylor Jul 9, 2014
e702873
Additions to decode get_observation responses from SOS2.0. Adding
peterataylor Jul 9, 2014
9299d76
Merge branch 'sos-decoder-waterml2' of https://github.com/peterataylo…
peterataylor Dec 14, 2014
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion .travis.yml
Expand Up @@ -14,7 +14,8 @@ install:
- if [ "$TRAVIS_PYTHON_VERSION" == "2.6" ]; then pip install -r requirements-2.6.txt; fi
- if [ "$LXML" == "true" ]; then pip install lxml; fi
script:
- python -m pytest -s
- python -m pytest
- pep8 owslib/wmts.py
notifications:
irc:
- "irc.freenode.org#geopython"
1 change: 1 addition & 0 deletions CREDITS.txt
Expand Up @@ -10,3 +10,4 @@
* Christian Ledermann <christian.ledermann@gmail.com>
* Sean Cowan <scowan@asascience.com>
* Kyle Wilcox <wilcox.kyle@gmail.com>
* Angelos Tzotsos <gcpp.kalxas@gmail.com>
2 changes: 1 addition & 1 deletion LICENSE.txt
Expand Up @@ -10,7 +10,7 @@ modification, are permitted provided that the following conditions are met:
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the University of North Carolina nor the names of
* Neither the name of the Ancient World Mapping Center nor the names of
its contributors may be used to endorse or promote products derived
from this software without specific prior written permission.

Expand Down
File renamed without changes.
50 changes: 39 additions & 11 deletions docs/en/index.rst
Expand Up @@ -5,11 +5,11 @@ OWSLib |release| documentation
.. toctree::
:maxdepth: 2

.. image:: http://www.ohloh.net/p/owslib/widgets/project_partner_badge.gif
.. image:: https://www.openhub.net/p/owslib/widgets/project_partner_badge.gif
:width: 193px
:height: 33px
:alt: OWSLib
:target: http://www.ohloh.net/p/owslib?ref=WidgetProjectPartnerBadge
:target: https://www.openhub.net/p/owslib?ref=WidgetProjectPartnerBadge

:Author: Tom Kralidis
:Contact: tomkralidis at gmail.com
Expand Down Expand Up @@ -62,7 +62,7 @@ Standards Support
+-------------------+---------------------+
| `WMTS`_ | 1.0.0 |
+-------------------+---------------------+
| `WaterML`_ | 1.0, 1.1 |
| `WaterML`_ | 1.0, 1.1, 2.0 |
+-------------------+---------------------+

Installation
Expand All @@ -71,7 +71,7 @@ Installation
Requirements
------------

OWSLib requires a Python interpreter, as well as `ElementTree <http://effbot.org/zone/element-index.htm>`_ or `lxml <http://codespeak.net/lxml>`_ for XML parsing.
OWSLib requires a Python interpreter, as well as `ElementTree <https://docs.python.org/2/library/xml.etree.elementtree.html>`_ or `lxml <http://lxml.de>`_ for XML parsing.

Install
-------
Expand All @@ -81,6 +81,8 @@ PyPI:
.. code-block:: bash

$ easy_install OWSLib
# pip works too
$ pip install OWSLib

Git:

Expand Down Expand Up @@ -110,6 +112,15 @@ RedHat Enterprise Linux
$ wget -O /etc/yum.repos.d/RHEL-CBS.repo http://download.opensuse.org/repositories/Application:/Geo/RHEL_6/Application:Geo.repo
$ yum install owslib

Fedora:

.. note::

As of Fedora 20, OWSLib is part of the Fedora core package collection

.. code-block:: bash
$ yum install OWSLib

Usage
=====

Expand Down Expand Up @@ -220,7 +231,9 @@ Search for bird data:

.. code-block:: python

>>> csw.getrecords(keywords=['birds'], maxrecords=20)
>>> from owslib.fes import PropertyIsEqualTo, PropertyIsLike, BBox
>>> birds_query = PropertyIsEqualTo('csw:AnyText', 'birds')
>>> csw.getrecords(constraints=[birds_query], maxrecords=20)
>>> csw.results
{'matches': 101, 'nextrecord': 21, 'returned': 20}
>>> for rec in csw.records:
Expand Down Expand Up @@ -252,16 +265,19 @@ Search for bird data in Canada:

.. code-block:: python

>>> csw.getrecords(keywords=['birds'],bbox=[-141,42,-52,84])
>>> bbox_query = BBox([-141,42,-52,84])
>>> csw.getrecords(constraints=[birds_query, bbox_query])
>>> csw.results
{'matches': 3, 'nextrecord': 0, 'returned': 3}
>>>

Search for 'birds' or 'fowl'
Search for keywords like 'birds' or 'fowl'

.. code-block:: python

>>> csw.getrecords(keywords=['birds', 'fowl'])
>>> birds_query_like = PropertyIsLike('dc:subject', '%birds%')
>>> fowl_query_like = PropertyIsLike('dc:subject', '%fowl%')
>>> csw.getrecords(constraints=[birds_query_like, fowl_query_like])
>>> csw.results
{'matches': 107, 'nextrecord': 11, 'returned': 10}
>>>
Expand Down Expand Up @@ -503,8 +519,8 @@ You can also submit a pre-made request encoded as WPS XML:
Output URL=http://cida.usgs.gov/climate/gdp/process/RetrieveResultServlet?id=5103866488472745994OUTPUT.f80e2a78-96a9-4343-9777-be60fac5b256


SOS
---
SOS 1.0
-------

GetCapabilities

Expand All @@ -514,6 +530,16 @@ GetObservation

.. include:: ../../tests/doctests/sos_10_ndbc_getobservation.txt

SOS 2.0
-------
Examples of service metadata and GetObservation

.. include:: ../../tests/doctests/sos_20_52n_geoviqua.txt

Using the GetObservation response decoder for O&M and WaterML2.0 results

.. include:: ../../tests/doctests/sos_20_timeseries_decoder_ioos.txt

SensorML
--------
.. include:: ../../tests/doctests/sml_ndbc_station.txt
Expand Down Expand Up @@ -661,6 +687,8 @@ Credits
.. _`OGC WMC`: http://www.opengeospatial.org/standards/wmc
.. _`OGC WPS`: http://www.opengeospatial.org/standards/wps
.. _`OGC SOS`: http://www.opengeospatial.org/standards/sos
.. _`OGC O&M`: http://www.opengeospatial.org/standards/om
.. _`OGC WaterML2.0`: http://www.opengeospatial.org/standards/waterml
.. _`OGC SensorML`: http://www.opengeospatial.org/standards/sensorml
.. _`OGC CSW`: http://www.opengeospatial.org/standards/cat
.. _`OGC WMTS`: http://www.opengeospatial.org/standards/wmts
Expand All @@ -674,4 +702,4 @@ Credits
.. _`freenode`: http://freenode.net/
.. _`ohloh`: http://www.ohloh.net/p/OWSLib
.. _`CIA.vc`: http://cia.vc/stats/project/OWSLib
.. _`WaterML`: http://his.cuahsi.org/wofws.html#waterml
.. _`WaterML1.0`: http://his.cuahsi.org/wofws.html#waterml
6 changes: 3 additions & 3 deletions docs/publish.sh
Expand Up @@ -4,13 +4,13 @@
THIS_DIR=`pwd`

make clean && make html
git clone git@github.com:geopython/OWSLib.git /tmp/OWSLib
cd /tmp/OWSLib
git clone git@github.com:geopython/OWSLib.git /tmp/OWSLib-$$
cd /tmp/OWSLib-$$
git checkout gh-pages
/bin/cp -rp $THIS_DIR/build/html/en/* .
git add .
git commit -am "update live docs [ci skip]"
git push origin gh-pages

cd $THIS_DIR
rm -fr /tmp/OWSLib
rm -fr /tmp/OWSLib-$$
28 changes: 22 additions & 6 deletions owslib/csw.py
Expand Up @@ -9,11 +9,13 @@

""" CSW request and response processor """

import base64
import inspect
import warnings
import StringIO
import random
from urllib import urlencode
from urllib2 import urlopen
from urllib2 import Request, urlopen

from owslib.util import OrderedDict

Expand All @@ -39,7 +41,8 @@ def get_namespaces():

class CatalogueServiceWeb:
""" csw request class """
def __init__(self, url, lang='en-US', version='2.0.2', timeout=10, skip_caps=False):
def __init__(self, url, lang='en-US', version='2.0.2', timeout=10, skip_caps=False,
username=None, password=None):
"""

Construct and process a GetCapabilities request
Expand All @@ -52,13 +55,17 @@ def __init__(self, url, lang='en-US', version='2.0.2', timeout=10, skip_caps=Fal
- version: version (default is '2.0.2')
- timeout: timeout in seconds
- skip_caps: whether to skip GetCapabilities processing on init (default is False)
- username: username for HTTP basic authentication
- password: password for HTTP basic authentication

"""

self.url = url
self.lang = lang
self.version = version
self.timeout = timeout
self.username = username
self.password = password
self.service = 'CSW'
self.exceptionreport = None
self.owscommon = ows.OwsCommon('1.0.0')
Expand Down Expand Up @@ -511,7 +518,7 @@ def _parseinsertresult(self):

def _parserecords(self, outputschema, esn):
if outputschema == namespaces['gmd']: # iso 19139
for i in self._exml.findall('.//'+util.nspath_eval('gmd:MD_Metadata', namespaces)):
for i in self._exml.findall('.//'+util.nspath_eval('gmd:MD_Metadata', namespaces)) or self._exml.findall('.//'+util.nspath_eval('gmi:MI_Metadata', namespaces)):
val = i.find(util.nspath_eval('gmd:fileIdentifier/gco:CharacterString', namespaces))
identifier = self._setidentifierkey(util.testXMLValue(val))
self.records[identifier] = MD_Metadata(i)
Expand Down Expand Up @@ -584,14 +591,21 @@ def _invoke(self):
# do HTTP request

if isinstance(self.request, basestring): # GET KVP
self.response = urlopen(self.request, timeout=self.timeout).read()
req = Request(self.request)
if self.username is not None and self.password is not None:
base64string = base64.encodestring('%s:%s' % (self.username, self.password))[:-1]
req.add_header('Authorization', 'Basic %s' % base64string)
self.response = urlopen(req, timeout=self.timeout).read()
else:
xml_post_url = self.url
# Get correct POST URL based on Operation list.
# If skip_caps=True, then self.operations has not been set, so use
# default URL.
if hasattr(self, 'operations'):
for op in self.operations:
caller = inspect.stack()[1][3]
if caller == 'getrecords2': caller = 'getrecords'
try:
op = self.get_operation_by_name(caller)
post_verbs = filter(lambda x: x.get('type').lower() == 'post', op.methods)
if len(post_verbs) > 1:
# Filter by constraints. We must match a PostEncoding of "XML"
Expand All @@ -602,6 +616,8 @@ def _invoke(self):
xml_post_url = post_verbs[0].get('url')
elif len(post_verbs) == 1:
xml_post_url = post_verbs[0].get('url')
except: # no such luck, just go with xml_post_url
pass

self.request = cleanup_namespaces(self.request)
# Add any namespaces used in the "typeNames" attribute of the
Expand All @@ -616,7 +632,7 @@ def _invoke(self):

self.request = util.element_to_string(self.request, encoding='utf-8')

self.response = util.http_post(xml_post_url, self.request, self.lang, self.timeout)
self.response = util.http_post(xml_post_url, self.request, self.lang, self.timeout, self.username, self.password)

# parse result see if it's XML
self._exml = etree.parse(StringIO.StringIO(self.response))
Expand Down
5 changes: 4 additions & 1 deletion owslib/feature/__init__.py
Expand Up @@ -119,7 +119,10 @@ def getGETGetFeatureRequest(self, typename=None, filter=None, bbox=None, feature
request['query'] = str(filter)
if typename:
typename = [typename] if type(typename) == type("") else typename
request['typename'] = ','.join(typename)
if self.version == "2.0.0":
request['typename'] = ','.join(typename)
else:
request['typenames'] = ','.join(typename)
if propertyname:
request['propertyname'] = ','.join(propertyname)
if featureversion:
Expand Down
4 changes: 2 additions & 2 deletions owslib/feature/wfs200.py
Expand Up @@ -255,7 +255,7 @@ def _getStoredQueries(self, timeout=30):

request = {'service': 'WFS', 'version': self.version, 'request': 'ListStoredQueries'}
encoded_request = urlencode(request)
u = urlopen(base_url + encoded_request, timeout=timeout)
u = urlopen(base_url, data=encoded_request, timeout=timeout)
tree=etree.fromstring(u.read())
tempdict={}
for sqelem in tree[:]:
Expand All @@ -275,7 +275,7 @@ def _getStoredQueries(self, timeout=30):
base_url = self.url
request = {'service': 'WFS', 'version': self.version, 'request': 'DescribeStoredQueries'}
encoded_request = urlencode(request)
u = urlopen(base_url + encoded_request, timeout=timeout)
u = urlopen(base_url, data=encoded_request, timeout=timeout)
tree=etree.fromstring(u.read())
tempdict2={}
for sqelem in tree[:]:
Expand Down
32 changes: 20 additions & 12 deletions owslib/iso.py
Expand Up @@ -247,9 +247,9 @@ def __init__(self, md=None, identtype=None):
self.distance = []
self.uom = []
self.resourcelanguage = []
self.creator = None
self.publisher = None
self.originator = None
self.creator = []
self.publisher = []
self.contributor = []
self.edition = None
self.abstract = None
self.purpose = None
Expand Down Expand Up @@ -347,17 +347,20 @@ def __init__(self, md=None, identtype=None):
if val is not None:
self.resourcelanguage.append(val)

val = md.find(util.nspath_eval('gmd:pointOfContact/gmd:CI_ResponsibleParty/gmd:organisationName', namespaces))
if val is not None:
val2 = val.find(util.nspath_eval('gmd:role/gmd:CI_RoleCode', namespaces))
if val2 is not None:
clv = _testCodeListValue(val)
self.creator = []
self.publisher = []
self.contributor = []
for val in md.findall(util.nspath_eval('gmd:pointOfContact/gmd:CI_ResponsibleParty', namespaces)):
role = val.find(util.nspath_eval('gmd:role/gmd:CI_RoleCode', namespaces))
if role is not None:
clv = _testCodeListValue(role)
rp = CI_ResponsibleParty(val)
if clv == 'originator':
self.creator = util.testXMLValue(val)
self.creator.append(rp)
elif clv == 'publisher':
self.publisher = util.testXMLValue(val)
elif clv == 'contributor':
self.originator = util.testXMLValue(val)
self.publisher.append(rp)
elif clv == 'author':
self.contributor.append(rp)

val = md.find(util.nspath_eval('gmd:edition/gco:CharacterString', namespaces))
self.edition = util.testXMLValue(val)
Expand Down Expand Up @@ -545,6 +548,8 @@ def __init__(self, md=None):
self.operations = []
self.operateson = []
else:
val=md.find(util.nspath_eval('gmd:citation/gmd:CI_Citation/gmd:title/gco:CharacterString', namespaces))
self.title=util.testXMLValue(val)
self.identtype = 'service'
val = md.find(util.nspath_eval('srv:serviceType/gco:LocalName', namespaces))
self.type = util.testXMLValue(val)
Expand All @@ -555,6 +560,9 @@ def __init__(self, md=None):
val = md.find(util.nspath_eval('srv:accessProperties/gmd:MD_StandardOrderProcess/gmd:fees/gco:CharacterString', namespaces))
self.fees = util.testXMLValue(val)

val = md.find(util.nspath_eval('srv:accessProperties/gmd:MD_StandardOrderProcess/gmd:fees/gco:CharacterString', namespaces))
self.fees = util.testXMLValue(val)

val = md.find(util.nspath_eval('srv:extent/gmd:EX_Extent', namespaces))

if val is not None:
Expand Down
2 changes: 2 additions & 0 deletions owslib/namespaces.py
Expand Up @@ -15,6 +15,7 @@ class Namespaces(object):
'fgdc' : 'http://www.opengis.net/cat/csw/csdgm',
'gco' : 'http://www.isotc211.org/2005/gco',
'gmd' : 'http://www.isotc211.org/2005/gmd',
'gmi' : 'http://www.isotc211.org/2005/gmi',
'gml' : 'http://www.opengis.net/gml',
'gml311': 'http://www.opengis.net/gml',
'gml32' : 'http://www.opengis.net/gml/3.2',
Expand Down Expand Up @@ -42,6 +43,7 @@ class Namespaces(object):
'swe20' : 'http://www.opengis.net/swe/2.0',
'swes' : 'http://www.opengis.net/swes/2.0',
'tml' : 'ttp://www.opengis.net/tml',
'wml2' : 'http://www.opengis.net/waterml/2.0',
'wfs' : 'http://www.opengis.net/wfs',
'wfs20' : 'http://www.opengis.net/wfs/2.0',
'wcs' : 'http://www.opengis.net/wcs',
Expand Down
2 changes: 2 additions & 0 deletions owslib/ows.py
Expand Up @@ -162,6 +162,8 @@ def __repr__(self):
class OperationsMetadata(object):
"""Initialize an OWS OperationMetadata construct"""
def __init__(self, elem, namespace=DEFAULT_OWS_NAMESPACE):
if 'name' not in elem.attrib: # This is not a valid element
return
self.name = elem.attrib['name']
self.formatOptions = ['text/xml']
parameters = []
Expand Down