mirror of
https://github.com/aykhans/AzSuicideDataVisualization.git
synced 2025-07-02 06:22:25 +00:00
Version 0.1
Added sidebar, Dashboard, Line Graph
This commit is contained in:
57
.venv/Lib/site-packages/openpyxl/descriptors/__init__.py
Normal file
57
.venv/Lib/site-packages/openpyxl/descriptors/__init__.py
Normal file
@ -0,0 +1,57 @@
|
||||
# Copyright (c) 2010-2022 openpyxl
|
||||
|
||||
from .base import *
|
||||
from .sequence import Sequence
|
||||
|
||||
|
||||
class MetaStrict(type):
|
||||
|
||||
def __new__(cls, clsname, bases, methods):
|
||||
for k, v in methods.items():
|
||||
if isinstance(v, Descriptor):
|
||||
v.name = k
|
||||
return type.__new__(cls, clsname, bases, methods)
|
||||
|
||||
|
||||
class MetaSerialisable(type):
|
||||
|
||||
def __new__(cls, clsname, bases, methods):
|
||||
attrs = []
|
||||
nested = []
|
||||
elements = []
|
||||
namespaced = []
|
||||
for k, v in methods.items():
|
||||
if isinstance(v, Descriptor):
|
||||
ns= getattr(v, 'namespace', None)
|
||||
if ns:
|
||||
namespaced.append((k, "{%s}%s" % (ns, k)))
|
||||
if getattr(v, 'nested', False):
|
||||
nested.append(k)
|
||||
elements.append(k)
|
||||
elif isinstance(v, Sequence):
|
||||
elements.append(k)
|
||||
elif isinstance(v, Typed):
|
||||
if hasattr(v.expected_type, 'to_tree'):
|
||||
elements.append(k)
|
||||
else:
|
||||
attrs.append(k)
|
||||
else:
|
||||
if not isinstance(v, Alias):
|
||||
attrs.append(k)
|
||||
|
||||
if methods.get('__attrs__') is None:
|
||||
methods['__attrs__'] = tuple(attrs)
|
||||
methods['__namespaced__'] = tuple(namespaced)
|
||||
if methods.get('__nested__') is None:
|
||||
methods['__nested__'] = tuple(sorted(nested))
|
||||
if methods.get('__elements__') is None:
|
||||
methods['__elements__'] = tuple(sorted(elements))
|
||||
return MetaStrict.__new__(cls, clsname, bases, methods)
|
||||
|
||||
|
||||
Strict = MetaStrict('Strict', (object,), {})
|
||||
|
||||
_Serialiasable = MetaSerialisable('_Serialisable', (object,), {})
|
||||
|
||||
#del MetaStrict
|
||||
#del MetaSerialisable
|
268
.venv/Lib/site-packages/openpyxl/descriptors/base.py
Normal file
268
.venv/Lib/site-packages/openpyxl/descriptors/base.py
Normal file
@ -0,0 +1,268 @@
|
||||
# Copyright (c) 2010-2022 openpyxl
|
||||
|
||||
|
||||
"""
|
||||
Based on Python Cookbook 3rd Edition, 8.13
|
||||
http://chimera.labs.oreilly.com/books/1230000000393/ch08.html#_discussiuncion_130
|
||||
"""
|
||||
|
||||
import datetime
|
||||
import re
|
||||
|
||||
from openpyxl.utils.datetime import from_ISO8601
|
||||
|
||||
from .namespace import namespaced
|
||||
|
||||
class Descriptor(object):
|
||||
|
||||
def __init__(self, name=None, **kw):
|
||||
self.name = name
|
||||
for k, v in kw.items():
|
||||
setattr(self, k, v)
|
||||
|
||||
def __set__(self, instance, value):
|
||||
instance.__dict__[self.name] = value
|
||||
|
||||
|
||||
class Typed(Descriptor):
|
||||
"""Values must of a particular type"""
|
||||
|
||||
expected_type = type(None)
|
||||
allow_none = False
|
||||
nested = False
|
||||
|
||||
def __init__(self, *args, **kw):
|
||||
super(Typed, self).__init__(*args, **kw)
|
||||
self.__doc__ = "Values must be of type {0}".format(self.expected_type)
|
||||
|
||||
def __set__(self, instance, value):
|
||||
if not isinstance(value, self.expected_type):
|
||||
if (not self.allow_none
|
||||
or (self.allow_none and value is not None)):
|
||||
raise TypeError('expected ' + str(self.expected_type))
|
||||
super(Typed, self).__set__(instance, value)
|
||||
|
||||
def __repr__(self):
|
||||
return self.__doc__
|
||||
|
||||
|
||||
def _convert(expected_type, value):
|
||||
"""
|
||||
Check value is of or can be converted to expected type.
|
||||
"""
|
||||
if not isinstance(value, expected_type):
|
||||
try:
|
||||
value = expected_type(value)
|
||||
except:
|
||||
raise TypeError('expected ' + str(expected_type))
|
||||
return value
|
||||
|
||||
|
||||
class Convertible(Typed):
|
||||
"""Values must be convertible to a particular type"""
|
||||
|
||||
def __set__(self, instance, value):
|
||||
if ((self.allow_none and value is not None)
|
||||
or not self.allow_none):
|
||||
value = _convert(self.expected_type, value)
|
||||
super(Convertible, self).__set__(instance, value)
|
||||
|
||||
|
||||
class Max(Convertible):
|
||||
"""Values must be less than a `max` value"""
|
||||
|
||||
expected_type = float
|
||||
allow_none = False
|
||||
|
||||
def __init__(self, **kw):
|
||||
if 'max' not in kw and not hasattr(self, 'max'):
|
||||
raise TypeError('missing max value')
|
||||
super(Max, self).__init__(**kw)
|
||||
|
||||
def __set__(self, instance, value):
|
||||
if ((self.allow_none and value is not None)
|
||||
or not self.allow_none):
|
||||
value = _convert(self.expected_type, value)
|
||||
if value > self.max:
|
||||
raise ValueError('Max value is {0}'.format(self.max))
|
||||
super(Max, self).__set__(instance, value)
|
||||
|
||||
|
||||
class Min(Convertible):
|
||||
"""Values must be greater than a `min` value"""
|
||||
|
||||
expected_type = float
|
||||
allow_none = False
|
||||
|
||||
def __init__(self, **kw):
|
||||
if 'min' not in kw and not hasattr(self, 'min'):
|
||||
raise TypeError('missing min value')
|
||||
super(Min, self).__init__(**kw)
|
||||
|
||||
def __set__(self, instance, value):
|
||||
if ((self.allow_none and value is not None)
|
||||
or not self.allow_none):
|
||||
value = _convert(self.expected_type, value)
|
||||
if value < self.min:
|
||||
raise ValueError('Min value is {0}'.format(self.min))
|
||||
super(Min, self).__set__(instance, value)
|
||||
|
||||
|
||||
class MinMax(Min, Max):
|
||||
"""Values must be greater than `min` value and less than a `max` one"""
|
||||
pass
|
||||
|
||||
|
||||
class Set(Descriptor):
|
||||
"""Value can only be from a set of know values"""
|
||||
|
||||
def __init__(self, name=None, **kw):
|
||||
if not 'values' in kw:
|
||||
raise TypeError("missing set of values")
|
||||
kw['values'] = set(kw['values'])
|
||||
super(Set, self).__init__(name, **kw)
|
||||
self.__doc__ = "Value must be one of {0}".format(self.values)
|
||||
|
||||
def __set__(self, instance, value):
|
||||
if value not in self.values:
|
||||
raise ValueError(self.__doc__)
|
||||
super(Set, self).__set__(instance, value)
|
||||
|
||||
|
||||
class NoneSet(Set):
|
||||
|
||||
"""'none' will be treated as None"""
|
||||
|
||||
def __init__(self, name=None, **kw):
|
||||
super(NoneSet, self).__init__(name, **kw)
|
||||
self.values.add(None)
|
||||
|
||||
def __set__(self, instance, value):
|
||||
if value == 'none':
|
||||
value = None
|
||||
super(NoneSet, self).__set__(instance, value)
|
||||
|
||||
|
||||
class Integer(Convertible):
|
||||
|
||||
expected_type = int
|
||||
|
||||
|
||||
class Float(Convertible):
|
||||
|
||||
expected_type = float
|
||||
|
||||
|
||||
class Bool(Convertible):
|
||||
|
||||
expected_type = bool
|
||||
|
||||
def __set__(self, instance, value):
|
||||
if isinstance(value, str):
|
||||
if value in ('false', 'f', '0'):
|
||||
value = False
|
||||
super(Bool, self).__set__(instance, value)
|
||||
|
||||
|
||||
class String(Typed):
|
||||
|
||||
expected_type = str
|
||||
|
||||
|
||||
class Text(String, Convertible):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class ASCII(Typed):
|
||||
|
||||
expected_type = bytes
|
||||
|
||||
|
||||
class Tuple(Typed):
|
||||
|
||||
expected_type = tuple
|
||||
|
||||
|
||||
class Length(Descriptor):
|
||||
|
||||
def __init__(self, name=None, **kw):
|
||||
if "length" not in kw:
|
||||
raise TypeError("value length must be supplied")
|
||||
super(Length, self).__init__(**kw)
|
||||
|
||||
|
||||
def __set__(self, instance, value):
|
||||
if len(value) != self.length:
|
||||
raise ValueError("Value must be length {0}".format(self.length))
|
||||
super(Length, self).__set__(instance, value)
|
||||
|
||||
|
||||
class Default(Typed):
|
||||
"""
|
||||
When called returns an instance of the expected type.
|
||||
Additional default values can be passed in to the descriptor
|
||||
"""
|
||||
|
||||
def __init__(self, name=None, **kw):
|
||||
if "defaults" not in kw:
|
||||
kw['defaults'] = {}
|
||||
super(Default, self).__init__(**kw)
|
||||
|
||||
def __call__(self):
|
||||
return self.expected_type()
|
||||
|
||||
|
||||
class Alias(Descriptor):
|
||||
"""
|
||||
Aliases can be used when either the desired attribute name is not allowed
|
||||
or confusing in Python (eg. "type") or a more descriptve name is desired
|
||||
(eg. "underline" for "u")
|
||||
"""
|
||||
|
||||
def __init__(self, alias):
|
||||
self.alias = alias
|
||||
|
||||
def __set__(self, instance, value):
|
||||
setattr(instance, self.alias, value)
|
||||
|
||||
def __get__(self, instance, cls):
|
||||
return getattr(instance, self.alias)
|
||||
|
||||
|
||||
class MatchPattern(Descriptor):
|
||||
"""Values must match a regex pattern """
|
||||
allow_none = False
|
||||
|
||||
def __init__(self, name=None, **kw):
|
||||
if 'pattern' not in kw and not hasattr(self, 'pattern'):
|
||||
raise TypeError('missing pattern value')
|
||||
|
||||
super(MatchPattern, self).__init__(name, **kw)
|
||||
self.test_pattern = re.compile(self.pattern, re.VERBOSE)
|
||||
|
||||
|
||||
def __set__(self, instance, value):
|
||||
|
||||
if value is None and not self.allow_none:
|
||||
raise ValueError("Value must not be none")
|
||||
|
||||
if ((self.allow_none and value is not None)
|
||||
or not self.allow_none):
|
||||
if not self.test_pattern.match(value):
|
||||
raise ValueError('Value does not match pattern {0}'.format(self.pattern))
|
||||
|
||||
super(MatchPattern, self).__set__(instance, value)
|
||||
|
||||
|
||||
class DateTime(Typed):
|
||||
|
||||
expected_type = datetime.datetime
|
||||
|
||||
def __set__(self, instance, value):
|
||||
if value is not None and isinstance(value, str):
|
||||
try:
|
||||
value = from_ISO8601(value)
|
||||
except ValueError:
|
||||
raise ValueError("Value must be ISO datetime format")
|
||||
super(DateTime, self).__set__(instance, value)
|
112
.venv/Lib/site-packages/openpyxl/descriptors/excel.py
Normal file
112
.venv/Lib/site-packages/openpyxl/descriptors/excel.py
Normal file
@ -0,0 +1,112 @@
|
||||
#copyright openpyxl 2010-2018
|
||||
|
||||
"""
|
||||
Excel specific descriptors
|
||||
"""
|
||||
|
||||
from openpyxl.xml.constants import REL_NS
|
||||
from openpyxl.compat import safe_string
|
||||
from openpyxl.xml.functions import Element
|
||||
|
||||
from . import (
|
||||
MatchPattern,
|
||||
MinMax,
|
||||
Integer,
|
||||
String,
|
||||
Sequence,
|
||||
)
|
||||
from .serialisable import Serialisable
|
||||
|
||||
|
||||
class HexBinary(MatchPattern):
|
||||
|
||||
pattern = "[0-9a-fA-F]+$"
|
||||
|
||||
|
||||
class UniversalMeasure(MatchPattern):
|
||||
|
||||
pattern = r"[0-9]+(\.[0-9]+)?(mm|cm|in|pt|pc|pi)"
|
||||
|
||||
|
||||
class TextPoint(MinMax):
|
||||
"""
|
||||
Size in hundredths of points.
|
||||
In theory other units of measurement can be used but these are unbounded
|
||||
"""
|
||||
expected_type = int
|
||||
|
||||
min = -400000
|
||||
max = 400000
|
||||
|
||||
|
||||
Coordinate = Integer
|
||||
|
||||
|
||||
class Percentage(MinMax):
|
||||
|
||||
pattern = r"((100)|([0-9][0-9]?))(\.[0-9][0-9]?)?%" # strict
|
||||
min = -1000000
|
||||
max = 1000000
|
||||
|
||||
def __set__(self, instance, value):
|
||||
if isinstance(value, str) and "%" in value:
|
||||
value = value.replace("%", "")
|
||||
value = int(float(value) * 1000)
|
||||
super(Percentage, self).__set__(instance, value)
|
||||
|
||||
|
||||
class Extension(Serialisable):
|
||||
|
||||
uri = String()
|
||||
|
||||
def __init__(self,
|
||||
uri=None,
|
||||
):
|
||||
self.uri = uri
|
||||
|
||||
|
||||
class ExtensionList(Serialisable):
|
||||
|
||||
ext = Sequence(expected_type=Extension)
|
||||
|
||||
def __init__(self,
|
||||
ext=(),
|
||||
):
|
||||
self.ext = ext
|
||||
|
||||
|
||||
class Relation(String):
|
||||
|
||||
namespace = REL_NS
|
||||
allow_none = True
|
||||
|
||||
|
||||
class Base64Binary(MatchPattern):
|
||||
# http://www.w3.org/TR/xmlschema11-2/#nt-Base64Binary
|
||||
pattern = "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$"
|
||||
|
||||
|
||||
class Guid(MatchPattern):
|
||||
# https://msdn.microsoft.com/en-us/library/dd946381(v=office.12).aspx
|
||||
pattern = r"{[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}\}"
|
||||
|
||||
|
||||
class CellRange(MatchPattern):
|
||||
|
||||
pattern = r"^[$]?([A-Za-z]{1,3})[$]?(\d+)(:[$]?([A-Za-z]{1,3})[$]?(\d+)?)?$|^[A-Za-z]{1,3}:[A-Za-z]{1,3}$"
|
||||
allow_none = True
|
||||
|
||||
def __set__(self, instance, value):
|
||||
|
||||
if value is not None:
|
||||
value = value.upper()
|
||||
super(CellRange, self).__set__(instance, value)
|
||||
|
||||
|
||||
def _explicit_none(tagname, value, namespace=None):
|
||||
"""
|
||||
Override serialisation because explicit none required
|
||||
"""
|
||||
if namespace is not None:
|
||||
tagname = "{%s}%s" % (namespace, tagname)
|
||||
return Element(tagname, val=safe_string(value))
|
12
.venv/Lib/site-packages/openpyxl/descriptors/namespace.py
Normal file
12
.venv/Lib/site-packages/openpyxl/descriptors/namespace.py
Normal file
@ -0,0 +1,12 @@
|
||||
# copyright openpyxl 2010-2015
|
||||
|
||||
|
||||
def namespaced(obj, tagname, namespace=None):
|
||||
"""
|
||||
Utility to create a namespaced tag for an object
|
||||
"""
|
||||
|
||||
namespace = getattr(obj, "namespace", None) or namespace
|
||||
if namespace is not None:
|
||||
tagname = "{%s}%s" % (namespace, tagname)
|
||||
return tagname
|
131
.venv/Lib/site-packages/openpyxl/descriptors/nested.py
Normal file
131
.venv/Lib/site-packages/openpyxl/descriptors/nested.py
Normal file
@ -0,0 +1,131 @@
|
||||
#copyright openpyxl 2010-2015
|
||||
|
||||
"""
|
||||
Generic serialisable classes
|
||||
"""
|
||||
from .base import (
|
||||
Convertible,
|
||||
Bool,
|
||||
Descriptor,
|
||||
NoneSet,
|
||||
MinMax,
|
||||
Set,
|
||||
Float,
|
||||
Integer,
|
||||
String,
|
||||
Text,
|
||||
)
|
||||
from .sequence import Sequence
|
||||
from openpyxl.compat import safe_string
|
||||
from openpyxl.xml.functions import Element, localname, whitespace
|
||||
|
||||
|
||||
class Nested(Descriptor):
|
||||
|
||||
nested = True
|
||||
attribute = "val"
|
||||
|
||||
def __set__(self, instance, value):
|
||||
if hasattr(value, "tag"):
|
||||
tag = localname(value)
|
||||
if tag != self.name:
|
||||
raise ValueError("Tag does not match attribute")
|
||||
|
||||
value = self.from_tree(value)
|
||||
super(Nested, self).__set__(instance, value)
|
||||
|
||||
|
||||
def from_tree(self, node):
|
||||
return node.get(self.attribute)
|
||||
|
||||
|
||||
def to_tree(self, tagname=None, value=None, namespace=None):
|
||||
namespace = getattr(self, "namespace", namespace)
|
||||
if value is not None:
|
||||
if namespace is not None:
|
||||
tagname = "{%s}%s" % (namespace, tagname)
|
||||
value = safe_string(value)
|
||||
return Element(tagname, {self.attribute:value})
|
||||
|
||||
|
||||
class NestedValue(Nested, Convertible):
|
||||
"""
|
||||
Nested tag storing the value on the 'val' attribute
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class NestedText(NestedValue):
|
||||
"""
|
||||
Represents any nested tag with the value as the contents of the tag
|
||||
"""
|
||||
|
||||
|
||||
def from_tree(self, node):
|
||||
return node.text
|
||||
|
||||
|
||||
def to_tree(self, tagname=None, value=None, namespace=None):
|
||||
namespace = getattr(self, "namespace", namespace)
|
||||
if value is not None:
|
||||
if namespace is not None:
|
||||
tagname = "{%s}%s" % (namespace, tagname)
|
||||
el = Element(tagname)
|
||||
el.text = safe_string(value)
|
||||
whitespace(el)
|
||||
return el
|
||||
|
||||
|
||||
class NestedFloat(NestedValue, Float):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class NestedInteger(NestedValue, Integer):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class NestedString(NestedValue, String):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class NestedBool(NestedValue, Bool):
|
||||
|
||||
|
||||
def from_tree(self, node):
|
||||
return node.get("val", True)
|
||||
|
||||
|
||||
class NestedNoneSet(Nested, NoneSet):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class NestedSet(Nested, Set):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class NestedMinMax(Nested, MinMax):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class EmptyTag(Nested, Bool):
|
||||
|
||||
"""
|
||||
Boolean if a tag exists or not.
|
||||
"""
|
||||
|
||||
def from_tree(self, node):
|
||||
return True
|
||||
|
||||
|
||||
def to_tree(self, tagname=None, value=None, namespace=None):
|
||||
if value:
|
||||
namespace = getattr(self, "namespace", namespace)
|
||||
if namespace is not None:
|
||||
tagname = "{%s}%s" % (namespace, tagname)
|
||||
return Element(tagname)
|
127
.venv/Lib/site-packages/openpyxl/descriptors/sequence.py
Normal file
127
.venv/Lib/site-packages/openpyxl/descriptors/sequence.py
Normal file
@ -0,0 +1,127 @@
|
||||
# copyright openpyxl 2010-2015
|
||||
|
||||
from openpyxl.compat import safe_string
|
||||
from openpyxl.xml.functions import Element
|
||||
from openpyxl.utils.indexed_list import IndexedList
|
||||
|
||||
from .base import Descriptor, Alias, _convert
|
||||
from .namespace import namespaced
|
||||
|
||||
|
||||
class Sequence(Descriptor):
|
||||
"""
|
||||
A sequence (list or tuple) that may only contain objects of the declared
|
||||
type
|
||||
"""
|
||||
|
||||
expected_type = type(None)
|
||||
seq_types = (list, tuple)
|
||||
idx_base = 0
|
||||
unique = False
|
||||
|
||||
|
||||
def __set__(self, instance, seq):
|
||||
if not isinstance(seq, self.seq_types):
|
||||
raise TypeError("Value must be a sequence")
|
||||
seq = [_convert(self.expected_type, value) for value in seq]
|
||||
if self.unique:
|
||||
seq = IndexedList(seq)
|
||||
|
||||
super(Sequence, self).__set__(instance, seq)
|
||||
|
||||
|
||||
def to_tree(self, tagname, obj, namespace=None):
|
||||
"""
|
||||
Convert the sequence represented by the descriptor to an XML element
|
||||
"""
|
||||
for idx, v in enumerate(obj, self.idx_base):
|
||||
if hasattr(v, "to_tree"):
|
||||
el = v.to_tree(tagname, idx)
|
||||
else:
|
||||
tagname = namespaced(obj, tagname, namespace)
|
||||
el = Element(tagname)
|
||||
el.text = safe_string(v)
|
||||
yield el
|
||||
|
||||
|
||||
class ValueSequence(Sequence):
|
||||
"""
|
||||
A sequence of primitive types that are stored as a single attribute.
|
||||
"val" is the default attribute
|
||||
"""
|
||||
|
||||
attribute = "val"
|
||||
|
||||
|
||||
def to_tree(self, tagname, obj, namespace=None):
|
||||
tagname = namespaced(self, tagname, namespace)
|
||||
for v in obj:
|
||||
yield Element(tagname, {self.attribute:safe_string(v)})
|
||||
|
||||
|
||||
def from_tree(self, node):
|
||||
|
||||
return node.get(self.attribute)
|
||||
|
||||
|
||||
class NestedSequence(Sequence):
|
||||
"""
|
||||
Wrap a sequence in an containing object
|
||||
"""
|
||||
|
||||
count = False
|
||||
|
||||
def to_tree(self, tagname, obj, namespace=None):
|
||||
tagname = namespaced(self, tagname, namespace)
|
||||
container = Element(tagname)
|
||||
if self.count:
|
||||
container.set('count', str(len(obj)))
|
||||
for v in obj:
|
||||
container.append(v.to_tree())
|
||||
return container
|
||||
|
||||
|
||||
def from_tree(self, node):
|
||||
return [self.expected_type.from_tree(el) for el in node]
|
||||
|
||||
|
||||
class MultiSequence(Sequence):
|
||||
"""
|
||||
Sequences can contain objects with different tags
|
||||
"""
|
||||
|
||||
def __set__(self, instance, seq):
|
||||
if not isinstance(seq, (tuple, list)):
|
||||
raise ValueError("Value must be a sequence")
|
||||
seq = list(seq)
|
||||
Descriptor.__set__(self, instance, seq)
|
||||
|
||||
|
||||
def to_tree(self, tagname, obj, namespace=None):
|
||||
"""
|
||||
Convert the sequence represented by the descriptor to an XML element
|
||||
"""
|
||||
for v in obj:
|
||||
el = v.to_tree(namespace=namespace)
|
||||
yield el
|
||||
|
||||
|
||||
class MultiSequencePart(Alias):
|
||||
"""
|
||||
Allow a multisequence to be built up from parts
|
||||
|
||||
Excluded from the instance __elements__ or __attrs__ as is effectively an Alias
|
||||
"""
|
||||
|
||||
def __init__(self, expected_type, store):
|
||||
self.expected_type = expected_type
|
||||
self.store = store
|
||||
|
||||
|
||||
def __set__(self, instance, value):
|
||||
value = _convert(self.expected_type, value)
|
||||
instance.__dict__[self.store].append(value)
|
||||
|
||||
|
||||
def __get__(self, instance, cls):
|
||||
return self
|
240
.venv/Lib/site-packages/openpyxl/descriptors/serialisable.py
Normal file
240
.venv/Lib/site-packages/openpyxl/descriptors/serialisable.py
Normal file
@ -0,0 +1,240 @@
|
||||
# copyright openpyxl 2010-2015
|
||||
|
||||
from copy import copy
|
||||
from keyword import kwlist
|
||||
KEYWORDS = frozenset(kwlist)
|
||||
|
||||
from . import Descriptor
|
||||
from . import _Serialiasable
|
||||
from .sequence import (
|
||||
Sequence,
|
||||
NestedSequence,
|
||||
MultiSequencePart,
|
||||
)
|
||||
from .namespace import namespaced
|
||||
|
||||
from openpyxl.compat import safe_string
|
||||
from openpyxl.xml.functions import (
|
||||
Element,
|
||||
localname,
|
||||
)
|
||||
|
||||
seq_types = (list, tuple)
|
||||
|
||||
class Serialisable(_Serialiasable):
|
||||
"""
|
||||
Objects can serialise to XML their attributes and child objects.
|
||||
The following class attributes are created by the metaclass at runtime:
|
||||
__attrs__ = attributes
|
||||
__nested__ = single-valued child treated as an attribute
|
||||
__elements__ = child elements
|
||||
"""
|
||||
|
||||
__attrs__ = None
|
||||
__nested__ = None
|
||||
__elements__ = None
|
||||
__namespaced__ = None
|
||||
|
||||
idx_base = 0
|
||||
|
||||
@property
|
||||
def tagname(self):
|
||||
raise(NotImplementedError)
|
||||
|
||||
namespace = None
|
||||
|
||||
@classmethod
|
||||
def from_tree(cls, node):
|
||||
"""
|
||||
Create object from XML
|
||||
"""
|
||||
# strip known namespaces from attributes
|
||||
attrib = dict(node.attrib)
|
||||
for key, ns in cls.__namespaced__:
|
||||
if ns in attrib:
|
||||
attrib[key] = attrib[ns]
|
||||
del attrib[ns]
|
||||
|
||||
# strip attributes with unknown namespaces
|
||||
for key in list(attrib):
|
||||
if key.startswith('{'):
|
||||
del attrib[key]
|
||||
elif key in KEYWORDS:
|
||||
attrib["_" + key] = attrib[key]
|
||||
del attrib[key]
|
||||
elif "-" in key:
|
||||
n = key.replace("-", "_")
|
||||
attrib[n] = attrib[key]
|
||||
del attrib[key]
|
||||
|
||||
if node.text and "attr_text" in cls.__attrs__:
|
||||
attrib["attr_text"] = node.text
|
||||
|
||||
for el in node:
|
||||
tag = localname(el)
|
||||
if tag in KEYWORDS:
|
||||
tag = "_" + tag
|
||||
desc = getattr(cls, tag, None)
|
||||
if desc is None or isinstance(desc, property):
|
||||
continue
|
||||
|
||||
if hasattr(desc, 'from_tree'):
|
||||
#descriptor manages conversion
|
||||
obj = desc.from_tree(el)
|
||||
else:
|
||||
if hasattr(desc.expected_type, "from_tree"):
|
||||
#complex type
|
||||
obj = desc.expected_type.from_tree(el)
|
||||
else:
|
||||
#primitive
|
||||
obj = el.text
|
||||
|
||||
if isinstance(desc, NestedSequence):
|
||||
attrib[tag] = obj
|
||||
elif isinstance(desc, Sequence):
|
||||
attrib.setdefault(tag, [])
|
||||
attrib[tag].append(obj)
|
||||
elif isinstance(desc, MultiSequencePart):
|
||||
attrib.setdefault(desc.store, [])
|
||||
attrib[desc.store].append(obj)
|
||||
else:
|
||||
attrib[tag] = obj
|
||||
|
||||
return cls(**attrib)
|
||||
|
||||
|
||||
def to_tree(self, tagname=None, idx=None, namespace=None):
|
||||
|
||||
if tagname is None:
|
||||
tagname = self.tagname
|
||||
|
||||
# keywords have to be masked
|
||||
if tagname.startswith("_"):
|
||||
tagname = tagname[1:]
|
||||
|
||||
tagname = namespaced(self, tagname, namespace)
|
||||
namespace = getattr(self, "namespace", namespace)
|
||||
|
||||
attrs = dict(self)
|
||||
for key, ns in self.__namespaced__:
|
||||
if key in attrs:
|
||||
attrs[ns] = attrs[key]
|
||||
del attrs[key]
|
||||
|
||||
el = Element(tagname, attrs)
|
||||
if "attr_text" in self.__attrs__:
|
||||
el.text = safe_string(getattr(self, "attr_text"))
|
||||
|
||||
for child_tag in self.__elements__:
|
||||
desc = getattr(self.__class__, child_tag, None)
|
||||
obj = getattr(self, child_tag)
|
||||
if hasattr(desc, "namespace") and hasattr(obj, 'namespace'):
|
||||
obj.namespace = desc.namespace
|
||||
|
||||
if isinstance(obj, seq_types):
|
||||
if isinstance(desc, NestedSequence):
|
||||
# wrap sequence in container
|
||||
if not obj:
|
||||
continue
|
||||
nodes = [desc.to_tree(child_tag, obj, namespace)]
|
||||
elif isinstance(desc, Sequence):
|
||||
# sequence
|
||||
desc.idx_base = self.idx_base
|
||||
nodes = (desc.to_tree(child_tag, obj, namespace))
|
||||
else: # property
|
||||
nodes = (v.to_tree(child_tag, namespace) for v in obj)
|
||||
for node in nodes:
|
||||
el.append(node)
|
||||
else:
|
||||
if child_tag in self.__nested__:
|
||||
node = desc.to_tree(child_tag, obj, namespace)
|
||||
elif obj is None:
|
||||
continue
|
||||
else:
|
||||
node = obj.to_tree(child_tag)
|
||||
if node is not None:
|
||||
el.append(node)
|
||||
return el
|
||||
|
||||
|
||||
def __iter__(self):
|
||||
for attr in self.__attrs__:
|
||||
value = getattr(self, attr)
|
||||
if attr.startswith("_"):
|
||||
attr = attr[1:]
|
||||
elif attr != "attr_text" and "_" in attr:
|
||||
desc = getattr(self.__class__, attr)
|
||||
if getattr(desc, "hyphenated", False):
|
||||
attr = attr.replace("_", "-")
|
||||
if attr != "attr_text" and value is not None:
|
||||
yield attr, safe_string(value)
|
||||
|
||||
|
||||
def __eq__(self, other):
|
||||
if not self.__class__ == other.__class__:
|
||||
return False
|
||||
elif not dict(self) == dict(other):
|
||||
return False
|
||||
for el in self.__elements__:
|
||||
if getattr(self, el) != getattr(other, el):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
s = u"<{0}.{1} object>\nParameters:".format(
|
||||
self.__module__,
|
||||
self.__class__.__name__
|
||||
)
|
||||
args = []
|
||||
for k in self.__attrs__ + self.__elements__:
|
||||
v = getattr(self, k)
|
||||
if isinstance(v, Descriptor):
|
||||
v = None
|
||||
args.append(u"{0}={1}".format(k, repr(v)))
|
||||
args = u", ".join(args)
|
||||
|
||||
return u"\n".join([s, args])
|
||||
|
||||
|
||||
def __hash__(self):
|
||||
fields = []
|
||||
for attr in self.__attrs__ + self.__elements__:
|
||||
val = getattr(self, attr)
|
||||
if isinstance(val, list):
|
||||
val = tuple(val)
|
||||
fields.append(val)
|
||||
|
||||
return hash(tuple(fields))
|
||||
|
||||
|
||||
def __add__(self, other):
|
||||
if type(self) != type(other):
|
||||
raise TypeError("Cannot combine instances of different types")
|
||||
vals = {}
|
||||
for attr in self.__attrs__:
|
||||
vals[attr] = getattr(self, attr) or getattr(other, attr)
|
||||
for el in self.__elements__:
|
||||
a = getattr(self, el)
|
||||
b = getattr(other, el)
|
||||
if a and b:
|
||||
vals[el] = a + b
|
||||
else:
|
||||
vals[el] = a or b
|
||||
return self.__class__(**vals)
|
||||
|
||||
|
||||
def __copy__(self):
|
||||
# serialise to xml and back to avoid shallow copies
|
||||
xml = self.to_tree(tagname="dummy")
|
||||
cp = self.__class__.from_tree(xml)
|
||||
# copy any non-persisted attributed
|
||||
for k in self.__dict__:
|
||||
if k not in self.__attrs__ + self.__elements__:
|
||||
v = copy(getattr(self, k))
|
||||
setattr(cp, k, v)
|
||||
return cp
|
18
.venv/Lib/site-packages/openpyxl/descriptors/slots.py
Normal file
18
.venv/Lib/site-packages/openpyxl/descriptors/slots.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Metaclass for mixing slots and descriptors
|
||||
# From "Programming in Python 3" by Mark Summerfield Ch.8 p. 383
|
||||
|
||||
class AutoSlotProperties(type):
|
||||
|
||||
def __new__(mcl, classname, bases, dictionary):
|
||||
slots = list(dictionary.get("__slots__", []))
|
||||
for getter_name in [key for key in dictionary if key.startswith("get_")]:
|
||||
name = getter_name
|
||||
slots.append("__" + name)
|
||||
getter = dictionary.pop(getter_name)
|
||||
setter = dictionary.get(setter_name, None)
|
||||
if (setter is not None
|
||||
and isinstance(setter, collections.Callable)):
|
||||
del dictionary[setter_name]
|
||||
dictionary[name] = property(getter. setter)
|
||||
dictionary["__slots__"] = tuple(slots)
|
||||
return super().__new__(mcl, classname, bases, dictionary)
|
Reference in New Issue
Block a user