Coverage for python / felis / types.py: 91%
44 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-05-07 08:14 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-05-07 08:14 +0000
1"""Define the supported Felis datatypes."""
3# This file is part of felis.
4#
5# Developed for the LSST Data Management System.
6# This product includes software developed by the LSST Project
7# (https://www.lsst.org).
8# See the COPYRIGHT file at the top-level directory of this distribution
9# for details of code ownership.
10#
11# This program is free software: you can redistribute it and/or modify
12# it under the terms of the GNU General Public License as published by
13# the Free Software Foundation, either version 3 of the License, or
14# (at your option) any later version.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19# GNU General Public License for more details.
20#
21# You should have received a copy of the GNU General Public License
22# along with this program. If not, see <https://www.gnu.org/licenses/>.
24from __future__ import annotations
26from typing import Any
28__all__ = [
29 "Binary",
30 "Boolean",
31 "Byte",
32 "Char",
33 "Double",
34 "FelisType",
35 "Float",
36 "Int",
37 "Long",
38 "Short",
39 "String",
40 "Text",
41 "Timestamp",
42 "Unicode",
43]
46class FelisType:
47 """Base class for a representation of Felis column types.
49 Notes
50 -----
51 This class plays a role of a metaclass without being an actual metaclass.
52 It provides a method to retrieve a class (type) given Felis type name.
53 There should be no instances of this class (or sub-classes), the utility
54 of the class hierarchy is in the type system itself.
55 """
57 felis_name: str
58 """Name of the type as defined in the Felis schema."""
60 votable_name: str
61 """Name of the type as defined in VOTable."""
63 is_numeric: bool
64 """Flag indicating if the type is numeric."""
66 is_sized: bool
67 """Flag indicating if the type is sized, meaning it requires a length."""
69 is_timestamp: bool
70 """Flag indicating if the type is a timestamp."""
72 _types: dict[str, type[FelisType]] = {}
73 """Dictionary of all known Felis types."""
75 @classmethod
76 def __init_subclass__(
77 cls,
78 /,
79 felis_name: str,
80 votable_name: str,
81 is_numeric: bool = False,
82 is_sized: bool = False,
83 is_timestamp: bool = False,
84 **kwargs: Any,
85 ):
86 """Register a new Felis type.
88 Parameters
89 ----------
90 felis_name
91 Name of the type.
92 votable_name
93 Name of the type as defined in VOTable.
94 is_numeric
95 Flag indicating if the type is numeric.
96 is_sized
97 Flag indicating if the type is sized.
98 is_timestamp
99 Flag indicating if the type is a timestamp.
100 kwargs
101 Additional keyword arguments.
102 """
103 super().__init_subclass__(**kwargs)
104 cls.felis_name = felis_name
105 cls.votable_name = votable_name
106 cls.is_numeric = is_numeric
107 cls.is_sized = is_sized
108 cls.is_timestamp = is_timestamp
109 cls._types[felis_name] = cls
111 @classmethod
112 def felis_type(cls, felis_name: str) -> type[FelisType]:
113 """Return specific Felis type for a given name.
115 Parameters
116 ----------
117 felis_name
118 Name of the felis type as defined in felis schema.
120 Returns
121 -------
122 `type` [ `FelisType` ]
123 A specific Felis type class.
125 Raises
126 ------
127 TypeError
128 Raised if ``felis_name`` does not correspond to a known type.
129 """
130 try:
131 return cls._types[felis_name]
132 except KeyError:
133 raise TypeError(f"Unknown felis type {felis_name!r}") from None
136class Boolean(FelisType, felis_name="boolean", votable_name="boolean", is_numeric=False):
137 """Felis definition of boolean type."""
140class Byte(FelisType, felis_name="byte", votable_name="unsignedByte", is_numeric=True):
141 """Felis definition of byte type."""
144class Short(FelisType, felis_name="short", votable_name="short", is_numeric=True):
145 """Felis definition of short integer type."""
148class Int(FelisType, felis_name="int", votable_name="int", is_numeric=True):
149 """Felis definition of integer type."""
152class Long(FelisType, felis_name="long", votable_name="long", is_numeric=True):
153 """Felis definition of long integer type."""
156class Float(FelisType, felis_name="float", votable_name="float", is_numeric=True):
157 """Felis definition of single precision floating point type."""
160class Double(FelisType, felis_name="double", votable_name="double", is_numeric=True):
161 """Felis definition of double precision floating point type."""
164class Char(FelisType, felis_name="char", votable_name="char", is_sized=True):
165 """Felis definition of character type."""
168class String(FelisType, felis_name="string", votable_name="char", is_sized=True):
169 """Felis definition of string type."""
172class Unicode(FelisType, felis_name="unicode", votable_name="unicodeChar", is_sized=True):
173 """Felis definition of unicode string type."""
176class Text(FelisType, felis_name="text", votable_name="char"):
177 """Felis definition of text type."""
180class Binary(FelisType, felis_name="binary", votable_name="unsignedByte", is_sized=True):
181 """Felis definition of binary type."""
184class Timestamp(FelisType, felis_name="timestamp", votable_name="char", is_timestamp=True):
185 """Felis definition of timestamp type."""