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

CAOM2.5 (CADC-13449) #186

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions caom2/caom2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
from .checksum import * # noqa
from .chunk import * # noqa
from .common import * # noqa
from .dali import * # noqa
from .diff import * # noqa
from .obs_reader_writer import * # noqa
from .observation import * # noqa
Expand Down
77 changes: 55 additions & 22 deletions caom2/caom2/artifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# ****************** CANADIAN ASTRONOMY DATA CENTRE *******************
# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES **************
#
# (c) 2022. (c) 2022.
# (c) 2025. (c) 2025.
# Government of Canada Gouvernement du Canada
# National Research Council Conseil national de recherches
# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6
Expand Down Expand Up @@ -74,10 +74,10 @@
from urllib.parse import urlparse

from . import caom_util
from .chunk import ProductType
from .common import AbstractCaomEntity
from .common import ChecksumURI, OrderedEnum
from .common import AbstractCaomEntity, CaomObject, compute_bucket
from .common import OrderedEnum
from .part import Part
from .chunk import DataLinkSemantics
from datetime import datetime


Expand All @@ -95,17 +95,39 @@ class ReleaseType(OrderedEnum):
META = "meta"


class ArtifactDescription(CaomObject):
""" Short description with a URI reference for details"""

def __init__(self, uri, description):
super().__init__()
try:
urlparse(uri)
except ValueError:
raise TypeError('Expected any IVOA URI for ArtifactDescription.uri, '
'received {}'.format(uri))
self._uri = uri
self._description = description

@property
def uri(self):
return self._uri

@property
def description(self):
return self._description


class Artifact(AbstractCaomEntity):
"""Contains the meta data assocaited with a file.
"""Contains the metadata associated with a file.

- location of the file (uri)
- the http content-type
- size of the file (content-lenght)

As well as a pointer (parts) to content of the file.

eg: Artifact('ad:CFHT/1234567o')
where 'ad:CFHT/1234567o' is a uri that refernce the file...
eg: Artifact('cadc:CFHT/1234567o')
where 'cadc:CFHT/1234567o' is an uri that reference the file...

"""

Expand All @@ -118,17 +140,23 @@ def __init__(self,
content_checksum=None,
content_release=None,
content_read_groups=None,
parts=None
parts=None,
description_id=None
):
"""
Initialize a Artifact instance.
Initialize an Artifact instance.

Arguments: uri of the artifact. eg:
vos://cadc.nrc.ca!vospace/APASS/apass_north/proc/100605/n100605.fz
ad:CFHT/123456p
"""
super(Artifact, self).__init__()
self.uri = uri
try:
urlparse(uri)
except ValueError:
raise TypeError('Expected URI for Artifact.uri, received {}'.format(uri))
self._uri = uri
self._uri_bucket = compute_bucket(uri)
self.product_type = product_type
self.release_type = release_type
self.content_type = content_type
Expand All @@ -139,6 +167,7 @@ def __init__(self,
if parts is None:
parts = caom_util.TypedOrderedDict(Part, )
self.parts = parts
self.description_id = description_id

def _key(self):
return self.uri
Expand All @@ -160,15 +189,9 @@ def uri(self):
"""
return self._uri

@uri.setter
def uri(self, value):
caom_util.type_check(value, str, 'uri')
uri = urlparse(value)
if not uri.scheme:
raise ValueError('URI without scheme: {}'.format(value))
uri_str = uri.geturl()
caom_util.value_check(value, None, None, 'uri', override=uri_str)
self._uri = uri_str
@property
def uri_bucket(self):
return self._uri_bucket

@property
def product_type(self):
Expand All @@ -183,7 +206,7 @@ def product_type(self):

@product_type.setter
def product_type(self, value):
caom_util.type_check(value, ProductType, "product_type", False)
caom_util.type_check(value, DataLinkSemantics, "product_type", False)
self._product_type = value

@property
Expand Down Expand Up @@ -235,7 +258,7 @@ def content_length(self, value):
def content_checksum(self):
"""the checksum value for the artifact data

type: ChecksumURI
type: uri

"""
return self._content_checksum
Expand All @@ -245,7 +268,7 @@ def content_checksum(self, value):
if value is None:
self._content_checksum = None
else:
caom_util.type_check(value, ChecksumURI, "checksum_uri", False)
caom_util.type_check(value, str, "checksum_uri", False)
self._content_checksum = value

@property
Expand Down Expand Up @@ -306,3 +329,13 @@ def parts(self, value):
caom_util.type_check(value, caom_util.TypedOrderedDict, 'parts',
override=False)
self._parts = value

@property
def description_id(self):
return self._description_id

@description_id.setter
def description_id(self, value):
if value is not None:
caom_util.type_check(value, str, 'description_id')
self._description_id = value
33 changes: 21 additions & 12 deletions caom2/caom2/caom_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# ****************** CANADIAN ASTRONOMY DATA CENTRE *******************
# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES **************
#
# (c) 2016. (c) 2016.
# (c) 2025. (c) 2025.
# Government of Canada Gouvernement du Canada
# National Research Council Conseil national de recherches
# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6
Expand Down Expand Up @@ -74,7 +74,6 @@
the first point of use could be implemented. This helps the data
engineer get the correct meta data more quickly.
"""

import sys
import collections
from datetime import datetime
Expand All @@ -84,7 +83,7 @@


__all__ = ['TypedList', 'TypedSet', 'TypedOrderedDict', 'ClassProperty',
'URISet']
'URISet', 'validate_uri']

# TODO both these are very bad, implement more sensibly
IVOA_DATE_FORMAT = "%Y-%m-%dT%H:%M:%S.%f"
Expand Down Expand Up @@ -235,8 +234,8 @@ def __repr__(self):

def check(self, v):
if not isinstance(v, self._oktypes):
raise TypeError("Wrong type in list. OK Types: {0}".
format(self._oktypes))
raise TypeError("Wrong type ({0}) in list. OK Types: {1}".
format(type(v), self._oktypes))

def __len__(self):
return len(self.list)
Expand Down Expand Up @@ -328,6 +327,22 @@ def __contains__(self, item):
return False


def validate_uri(uri, scheme=None):
"""
Validates a URI. If a scheme is provided, the URI must have that scheme.
:param uri:
:param scheme:
:raise TypeError: when uri not valid
"""
if uri:
tmp = urlsplit(uri)
if scheme and scheme != tmp.scheme:
raise TypeError("Invalid URI scheme: {}".format(uri))
if tmp.geturl() == uri:
return
raise TypeError("Invalid URI: " + uri)


class URISet(TypedSet):
"""
Class that customizes a TypedSet to check for URIs
Expand All @@ -350,13 +365,7 @@ def check(self, v):
:param v: value to check
:return:
"""
if v:
tmp = urlsplit(v)
if self.scheme and tmp.scheme != self.scheme:
raise TypeError("Invalid URI scheme: {}".format(v))
if tmp.geturl() == v:
return
raise TypeError("Invalid URI: " + v)
validate_uri(v, self.scheme)


class TypedOrderedDict(collections.OrderedDict):
Expand Down
Loading
Loading