Commit 384824a0 authored by M. Huang's avatar M. Huang
Browse files

rasionalize Finetime,toString()

parent ff6092f1
......@@ -50,12 +50,18 @@ runserver:
runpoolserver:
$(PYEXE) -m fdi.pns.runflaskserver --username=foo --password=bar -v --server=httppool_server $(S)
INSOPT =
PIPOPT = --disable-pip-version-check --no-color
install:
$(PYEXE) -m pip install $(INSOPT) -e .$(EXT) $(I)
$(PYEXE) -m pip install $(PIPOPT) -e .$(EXT) $(I)
uninstall:
$(PYEXE) -m pip uninstall $(INSOPT) fdi $(I)
$(PYEXE) -m pip uninstall $(PIPOPT) fdi $(I)
addsubmodule:
git submodule add --name leapseconds https://gist.github.com/92df922103ac9deb1a05 ext/leapseconds
update:
git submodule update --init --recursive
PNSDIR=~/pns
installpns:
......
#https://git-scm.com/book/en/v2/Git-Basics-Getting-a-Git-Repository
git add LICENSE README.rst CHANGELOG.rst setup.py MANIFEST.in .gitignore noxfile.py Makefile .readthedocs.yml .gitlab-ci.yml .dockerignore CONTRIBUTORS
git add LICENSE README.rst CHANGELOG.rst setup.py setup.cfg MANIFEST.in .gitignore noxfile.py Makefile .readthedocs.yml .gitmodules .gitlab-ci.yml .dockerignore CONTRIBUTORS
git add bin/reinstall bin/installpns bin/update bin/gitadd
git add resources
git add fdi/*.py
......
......@@ -35,7 +35,6 @@ class ArrayDataset(GenericDataset, Iterable):
def __init__(self, data=None,
unit=None,
description=None,
typ_=None,
shape=None,
typecode=None,
zInfo=None,
......
......@@ -29,12 +29,6 @@ _Model_Spec = {
'default': 'UNKNOWN',
'valid': '',
},
'type': {
'data_type': 'string',
'description': 'Type identification. Name of class.',
'default': 'ArrayDataset',
'valid': '',
},
'unit': {
'data_type': 'string',
'description': 'Unit of every element.',
......
......@@ -81,9 +81,12 @@ class Attributable(MetaDataHolder):
def setMeta(self, newMetadata):
""" Replaces the current MetaData with specified argument.
mh: Product will override this to add listener when meta is
replaced
Product will override this to add listener when meta is
replaced.
`_defaults` which usually is `self.zInfo` is added to new meta so `str(meta)` can ommit the parameters with default value.
"""
defs = self.zInfo['metadata'] if hasattr(self, 'zInfo') else None
newMetadata._defaults = defs
self._meta = newMetadata
def __getattribute__(self, name):
......
......@@ -48,7 +48,7 @@ class BaseProduct( AbstractComposite, Copyable, Serializable, EventSender):
=====
BaseProduct class schema 1.6 inheriting [None].
Automatically generated from fdi/dataset/resources/BaseProduct.yml on 2021-06-17 22:21:01.798753.
Automatically generated from fdi/dataset/resources/BaseProduct.yml on 2021-06-18 16:19:33.951506.
Description:
FDI base class data model
......
......@@ -3,9 +3,9 @@ from .serializable import Serializable
from .odict import ODict
from .eq import DeepEqual
from .copyable import Copyable
#from .metadata import ParameterTypes
# from .metadata import ParameterTypes
#from ext.leapseconds import leapseconds
import datetime
import pdb
from collections import OrderedDict
import logging
......@@ -56,7 +56,7 @@ class FineTime(Copyable, DeepEqual, Serializable):
RESOLUTION = 1000000 # microsecond
""" """
DEFAULT_FORMAT = '%Y-%m-%dT%H:%M:%S.%f UTC' # ISO
DEFAULT_FORMAT = '%Y-%m-%dT%H:%M:%S.%f' # ISO
RETURNFMT = '%s.%06d'
......@@ -85,7 +85,7 @@ class FineTime(Copyable, DeepEqual, Serializable):
return self.tai
def setTime(self, time):
""" Sets the time of this object.
""" Sets the time of this object.
If an integer is given, it will be taken as the TAI.
If a datetime object or a string code is given, the timezone will be set to UTC.
......@@ -128,6 +128,8 @@ class FineTime(Copyable, DeepEqual, Serializable):
self.tai = setTai
def getFormat(self):
""" `format` cannot be a property name as it is a built so`@format.setter` is not allowed.
"""
return self.format
def microsecondsSinceEPOCH(self):
......@@ -145,51 +147,56 @@ class FineTime(Copyable, DeepEqual, Serializable):
return int(self.RESOLUTION *
((dtm - self.EPOCH).total_seconds() + leapsec)+0.5)
def toDatetime(self, tai):
""" Return given FineTime as a Python Datetime. """
def toDatetime(self, tai=None):
""" Return given FineTime as a Python Datetime.
tai: if not given or given as `None`, return this object's time as a Python Datetime.
"""
leapsec = 0 # leap seconds to be implemented
if tai is None:
tai = self.tai
return datetime.timedelta(seconds=(float(tai) / self.RESOLUTION - leapsec))\
+ self.EPOCH
def toDate(self):
""" Return this time as a Python Datetime. """
# HCSS compatibility
toDate = toDatetime
return self.toDatetime(self.tai)
def isoutc(self, format='%Y-%m-%dT%H:%M:%S'):
def isoutc(self, format='%Y-%m-%dT%H:%M:%S.%f'):
""" Returns a String representation of this objet in ISO format without timezone. sub-second set to TIMESPEC.
format: time format. default '%Y-%m-%dT%H:%M:%S' prints like 2019-02-17T12:43:04.577000 """
s = self.tai / self.RESOLUTION
sub = s - int(s)
dt = datetime.timedelta(seconds=(s)) + self.EPOCH
# return dt.isoformat(timespec=self.TIMESPEC)
return self.RETURNFMT % (dt.strftime(format), int(sub*self.RESOLUTION+0.5))
def toString(self, level=0,
tablefmt='rst', tablefmt1='simple', tablefmt2='simple',
width=0, **kwds):
s = (self.tai + 0.0) / self.RESOLUTION
dt = datetime.timedelta(seconds=s) + self.EPOCH
return dt.strftime(format)
def toString(self, level=0, width=0, **kwds):
""" Returns a String representation of this object according to self.format.
prints like 2019-02-17T12:43:04.577000 TAI(...)"""
level: 0 prints like 2019-02-17T12:43:04.577000 TAI(...)
width: if non-zero, insert newline to break simplified output into shorter lines. For level=0 it is ``` #TODO ```
"""
tais = str(self.tai) if hasattr(self, 'tai') else 'Unknown'
fmt = self.format
if level == 0:
if width:
tstr = self.isoutc(
format='%Y-%m-%d\n%H:%M:%S') + '\n%s' % tais
tstr = self.isoutc(format=fmt) + '\n' + tais
s = tstr
else:
tstr = self.isoutc() + ' TAI(%s)' % tais
s = self.__class__.__name__ + \
'{' + tstr + ' fmt=' + self.format + '}'
tstr = self.isoutc(format=fmt) + ' TAI(%s)' % tais
s = tstr + ' format=' + self.format
elif level == 1:
if width:
tstr = self.isoutc(
format='%Y-%m-%d\n%H:%M:%S') + '\n%s' % tais
tstr = self.isoutc(format=fmt) + '\n%s' % tais
else:
tstr = self.isoutc() + ' TAI(%s)' % tais
tstr = self.isoutc(format=fmt) + ' (%s)' % tais
s = tstr
elif level == 2:
s = self.isoutc() + ' TAI(%s)' % tais
if width:
s = self.__class__.__name__ + '(' + \
self.isoutc(format=fmt).replace('T', '\n') + ')'
else:
s = self.__class__.__name__ + '(' + \
self.isoutc(format=fmt) + ')'
else:
s = tais
return s
......@@ -227,12 +234,12 @@ class FineTime(Copyable, DeepEqual, Serializable):
return super(FineTime, self).__ge__(obj)
def __repr__(self):
return self.toString(level=2)
co = ', '.join(str(k)+'=' + ('"'+v+'"' if issubclass(v.__class__, str)
else str(v)) for k, v in self.__getstate__().items())
return '<'+self.__class__.__name__ + ' ' + co + '>'
__str__ = toString
# __str__ = toString
def __getstate__(self):
""" Can be encoded with serializableEncoder """
......
......@@ -572,6 +572,11 @@ class MetaData(Composite, Copyable, Serializable, ParameterListener, DatasetEven
Note that replacing a parameter with the same name,
will keep the order. """
Table_Widths = [
{'name': 15, 'value': 20, 'unit': 7, 'type': 8,
'valid': 20, 'default': 17, 'code': 4, 'description': 21}
]
def __init__(self, copy=None, defaults=None, **kwds):
super(MetaData, self).__init__(**kwds)
if copy:
......@@ -639,14 +644,13 @@ class MetaData(Composite, Copyable, Serializable, ParameterListener, DatasetEven
level: 0 is the most detailed, 2 is the least,
tablefmt: format string in packae ``tabulate``, for level==0, tablefmt1 for level1, tablefmt2: format of 2D table data.
param_widths: controls how the attributes of every parameter are displayed in the table cells. If is set to -1, there is no cell-width limit. For finer control set a dictionary of parameter attitute names and how many characters wide its tsble cell is, 0 for ommiting the attributable. Default is
param_widths: controls how the attributes of every parameter are displayed in the table cells. If is set to -1, there is no cell-width limit. For finer control set a dictionary of parameter attitute names and how many characters wide its tsble cell is, 0 for ommiting the attributable. Default is `MetaData.Table_Widths[0]`. e.g.
``{'name': 8, 'value': 17, 'unit': 7, 'type': 8,
'valid': 25, 'default': 17, 'code': 4, 'description': 15}``
'valid': 20, 'default': 17, 'code': 4, 'description': 15}``
"""
if param_widths is None:
param_widths = {'name': 15, 'value': 20, 'unit': 7, 'type': 8,
'valid': 23, 'default': 17, 'code': 4, 'description': 21}
param_widths = MetaData.Table_Widths[0]
tab = []
# N parameters per row for level 1
N = 3
......
......@@ -18,8 +18,7 @@ class MetaDataHolder(object):
with defaults set to self.zInfo['metadata'].
"""
if meta is None:
defs = self.zInfo['metadata'] if hasattr(self, 'zInfo') else None
meta = metadata.MetaData(defaults=defs)
meta = metadata.MetaData()
self.setMeta(meta)
super(MetaDataHolder, self).__init__(**kwds)
......
......@@ -20,7 +20,7 @@ logger = logging.getLogger(__name__)
class Product(BaseProduct):
""" Product class schema 1.6 inheriting ['BaseProduct'].
Automatically generated from fdi/dataset/resources/Product.yml on 2021-06-16 15:34:51.375313.
Automatically generated from fdi/dataset/resources/Product.yml on 2021-06-18 16:19:33.999904.
Description:
Project level product
......
......@@ -9,11 +9,6 @@ metadata:
description: Description of this dataset
default: UNKNOWN
valid: ''
type:
data_type: string
description: Type identification. Name of class.
default: ArrayDataset
valid: ''
unit:
data_type: string
description: Unit of every element.
......
......@@ -14,12 +14,9 @@
│ creator │ UNKNOWN │ │ string │ None │ UNKNOWN │ B │ Generator of this product │
│ │ │ │ │ │ │ │ . │
├──────────────┼─────────────────┼────────┼──────────┼─────────┼─────────────────┼────────┼───────────────────────────┤
│ creationDate │ 1958-01-01 │ │ finetime │ None │ 1958-01-01 │ %Y-% │ Creation date of this pro │
│ │ 00:00:00.000000 │ │ │ │ 00:00:00.000000 │ m-%d │ duct │
│ │ 0 │ │ │ │ 0 │ T%H: │ │
│ │ │ │ │ │ │ %M:% │ │
│ │ │ │ │ │ │ S.%f │ │
│ │ │ │ │ │ │ UTC │ │
│ creationDate │ 1958-01-01 │ │ finetime │ None │ 1958-01-01 │ Q │ Creation date of this pro │
│ │ 00:00:00.000000 │ │ │ │ 00:00:00.000000 │ │ duct │
│ │ 0 │ │ │ │ 0 │ │ │
├──────────────┼─────────────────┼────────┼──────────┼─────────┼─────────────────┼────────┼───────────────────────────┤
│ rootCause │ UNKNOWN │ │ string │ None │ UNKNOWN │ B │ Reason of this run of pip │
│ │ │ │ │ │ │ │ eline. │
......
......@@ -14,12 +14,9 @@
│ creator │ UNKNOWN │ │ string │ None │ UNKNOWN │ B │ Generator of this product │
│ │ │ │ │ │ │ │ . │
├──────────────┼─────────────────┼────────┼──────────┼─────────┼─────────────────┼────────┼───────────────────────────┤
│ creationDate │ 1958-01-01 │ │ finetime │ None │ 1958-01-01 │ %Y-% │ Creation date of this pro │
│ │ 00:00:00.000000 │ │ │ │ 00:00:00.000000 │ m-%d │ duct │
│ │ 0 │ │ │ │ 0 │ T%H: │ │
│ │ │ │ │ │ │ %M:% │ │
│ │ │ │ │ │ │ S.%f │ │
│ │ │ │ │ │ │ UTC │ │
│ creationDate │ 1958-01-01 │ │ finetime │ None │ 1958-01-01 │ Q │ Creation date of this pro │
│ │ 00:00:00.000000 │ │ │ │ 00:00:00.000000 │ │ duct │
│ │ 0 │ │ │ │ 0 │ │ │
├──────────────┼─────────────────┼────────┼──────────┼─────────┼─────────────────┼────────┼───────────────────────────┤
│ rootCause │ UNKNOWN │ │ string │ None │ UNKNOWN │ B │ Reason of this run of pip │
│ │ │ │ │ │ │ │ eline. │
......@@ -29,19 +26,13 @@
│ FORMATV │ 1.6.0.10 │ │ string │ None │ 1.6.0.10 │ B │ Version of product schema │
│ │ │ │ │ │ │ │ and revision │
├──────────────┼─────────────────┼────────┼──────────┼─────────┼─────────────────┼────────┼───────────────────────────┤
│ startDate │ 1958-01-01 │ │ finetime │ None │ 1958-01-01 │ %Y-% │ Nominal start time of th │
│ │ 00:00:00.000000 │ │ │ │ 00:00:00.000000 │ m-%d │ is product. │
│ │ 0 │ │ │ │ 0 │ T%H: │ │
│ │ │ │ │ │ │ %M:% │ │
│ │ │ │ │ │ │ S.%f │ │
│ │ │ │ │ │ │ UTC │ │
├──────────────┼─────────────────┼────────┼──────────┼─────────┼─────────────────┼────────┼───────────────────────────┤
│ endDate │ 1958-01-01 │ │ finetime │ None │ 1958-01-01 │ %Y-% │ Nominal end time of this │
│ │ 00:00:00.000000 │ │ │ │ 00:00:00.000000 │ m-%d │ product. │
│ │ 0 │ │ │ │ 0 │ T%H: │ │
│ │ │ │ │ │ │ %M:% │ │
│ │ │ │ │ │ │ S.%f │ │
│ │ │ │ │ │ │ UTC │ │
│ startDate │ 1958-01-01 │ │ finetime │ None │ 1958-01-01 │ Q │ Nominal start time of th │
│ │ 00:00:00.000000 │ │ │ │ 00:00:00.000000 │ │ is product. │
│ │ 0 │ │ │ │ 0 │ │ │
├──────────────┼─────────────────┼────────┼──────────┼─────────┼─────────────────┼────────┼───────────────────────────┤
│ endDate │ 1958-01-01 │ │ finetime │ None │ 1958-01-01 │ Q │ Nominal end time of this │
│ │ 00:00:00.000000 │ │ │ │ 00:00:00.000000 │ │ product. │
│ │ 0 │ │ │ │ 0 │ │ │
├──────────────┼─────────────────┼────────┼──────────┼─────────┼─────────────────┼────────┼───────────────────────────┤
│ instrument │ UNKNOWN │ │ string │ None │ UNKNOWN │ B │ Instrument that generated │
│ │ │ │ │ │ │ │ data of this product │
......
# -*- coding: utf-8 -*-
$WARNING
$IMPORTS
from fdi.dataset.readonlydict import ReadOnlyDict
import copy
import logging
# create logger
logger = logging.getLogger(__name__)
# Data Model specification for mandatory components
$MODELSPEC
Model = ReadOnlyDict(_Model_Spec)
......@@ -9,11 +9,6 @@ metadata:
description: Description of this dataset
default: UNKNOWN
valid: ''
type:
data_type: string
description: Type identification. Name of class.
default: TableDataset
valid: ''
version:
data_type: string
description: Version of dataset
......
......@@ -507,7 +507,7 @@ Default is to return all columns.
tablefmt=tablefmt, tablefmt1=tablefmt1, tablefmt2=tablefmt2,
width=width, param_widths=param_widths,
**kwds)
return s + '{' + \
return s + 'data= {' + \
', '.join('"%s": %s' % (k, v.toString(
level=level,
tablefmt=tablefmt, tablefmt1=tablefmt1, tablefmt2=tablefmt,
......
# -*- coding: utf-8 -*-
# Automatically generated from fdi/dataset/resources/TableDataset_DataModel.yml. Do not edit.
from collections import OrderedDict
from fdi.dataset.readonlydict import ReadOnlyDict
import copy
import logging
# create logger
logger = logging.getLogger(__name__)
# Data Model specification for mandatory components
_Model_Spec = {
'name': 'TableDataset_DataModel',
'description': 'TableDataset class data model mandatory configuration',
'parents': [
None,
],
'schema': '1.6',
'metadata': {
'description': {
'data_type': 'string',
'description': 'Description of this dataset',
'default': 'UNKNOWN',
'valid': '',
},
'version': {
'data_type': 'string',
'description': 'Version of dataset',
'default': '0.1',
'valid': '',
},
'FORMATV': {
'data_type': 'string',
'description': 'Version of dataset schema and revision',
'default': '1.6.0.1',
'valid': '',
},
},
'datasets': {
},
}
Model = ReadOnlyDict(_Model_Spec)
......@@ -54,9 +54,8 @@ v = ArrayDataset(a1)
# Show it. This is the same as print(v) in a non-interactive environment.
v
# Create an ArrayDataset with built-in properties set.
v = ArrayDataset(data=a1, unit='ev', description='5 elements',
typ_='float', default=1.0, typecode='f')
# Create an ArrayDataset with some built-in properties set.
v = ArrayDataset(data=a1, unit='ev', description='5 elements', typecode='f')
#
# add some metadats (see more about meta data below)
v.meta['greeting'] = StringParameter('Hi there.')
......@@ -291,9 +290,10 @@ then = datetime(
2019, 2, 19, 1, 2, 3, 456789, tzinfo=timezone.utc)
# The value of the next parameter is valid from TAI=0 to 9876543210123456
valid_rule = {(0, 9876543210123456): 'alive'}
# display typecode set to 'year' (%Y)
v['b'] = DateParameter(FineTime(then), 'date param', default=99,
valid=valid_rule, typecode='%Y')
valid=valid_rule)
# display format set to 'year' (%Y)
v['b'].format = '%Y-%M'
# The value of the next parameter has an empty rule set and is always valid.
v['c'] = StringParameter(
'Right', 'str parameter. but only "" is allowed.', valid={'': 'empty'}, default='cliche', typecode='B')
......
import os
from setuptools import setup, find_packages
from setuptools import setup, find_packages, find_namespace_packages
# https://pythonhosted.org/an_example_pypi_project/setuptools.html
# https://code.tutsplus.com/tutorials/how-to-write-package-and-distribute-a-library-in-python--cms-28693
......@@ -26,7 +26,9 @@ setup(
license="LGPL v3",
keywords="dataset metadata processing product context serialization server URN RESTful API HCSS",
url="http://mercury.bao.ac.cn:9006/mh/fdi",
packages=find_packages(exclude=['tests', 'tmp']),
packages=find_packages(exclude=['tests', 'tmp', 'docs'])
# packages=find_namespace_packages(exclude=['tests', 'tmp', 'docs'],
# include=('ext',)),
include_package_data=True,
long_description=read('README.rst'),
long_description_content_type="text/x-rst",
......@@ -38,6 +40,10 @@ setup(
'tabulate>=0.8.7',
'paho-mqtt>=1.5.1',
],
entry_points={'console_scripts': [
'yaml2python=fdi.dataset.yaml2python:main']},
setup_requires=['pytest-runner'],
tests_require=['pytest', 'pytest-cov', ],
extras_require={
'DEV': [
'setuptools>=43.0.0',
......@@ -69,5 +75,3 @@ setup(
"License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
],
)
# @ git+https://github.com/mhuang001/sphinx-copybutton.git'
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment