class TimeSerieGenerator(HasTraits): """ Very basic time serie generator. """ code = Str('Dataset1') from_date = Date(today - datetime.timedelta(days=365)) to_date = Date(today) generate = Event timestamps = Property(depends_on='from_date,to_date') data = Property(depends_on='dates,generate') @cached_property def _get_data(self): days = (self.to_date - self.from_date).days results = np.cumprod(np.random.lognormal(0.0, 0.04, size=days)) return results @cached_property def _get_timestamps(self): # horry gorry conversion days = np.arange(self.from_date, self.to_date, dtype='datetime64[D]') seconds = days.astype('datetime64[s]') timestamps = seconds.astype(int) return timestamps ### Traits UI view ######################################################### traits_view = View(VGroup( HGroup('code'), HGroup('from_date', 'to_date'), HGroup(Spring(), Item('generate', editor=ButtonEditor(), show_label=False))), title='Generator', width=200, resizable=True)
class Image(HasTraits): """ An SEM image stored in a file. """ filename = File(exists=True) sample_id = Str() date_acquired = Date() operator = Str() scan_size = Tuple(Float, Float) image = Array(shape=(None, None), dtype='uint8') def __init__(self, filename, sample_id, date_acquired, operator, scan_size=(1e-5, 1e-5)): super().__init__() # initialize the primary attributes self.filename = filename self.sample_id = sample_id self.scan_size = scan_size self.operator = operator # useful secondary attributes self.scan_width, self.scan_height = self.scan_size
class Person(HasTraits): """ A simple class representing a person object. """ # The last name of the person as a string last_name = Str # The first name of the person as a string first_name = Str # The date of birth of the person dob = Date(datetime.date(1970, 1, 1)) # The age of the person computed from their dob age = Property(Int, depends_on='dob') # This method is called when the age of the person needs to # be computed def _get_age(self): today = datetime.date.today() dob = self.dob age = today.year - dob.year birthday_this_year = dob.replace(year=today.year) if today < birthday_this_year: age -= 1 return age
class SensitivityRecord(HasTraits): user = Str(dictable=True) note = Str(dictable=True) mass_spectrometer = Str(dictable=True) sensitivity = Float(dictable=True) create_date = Date(dictable=True) units = Str('mol/fA', dictable=True) def to_dict(self): d = {k: getattr(self, k) for k in self.traits(dictable=True)} cd = d['create_date'] if not cd: self.create_date = cd = datetime.now() d['create_date'] = cd.strftime(DATE_FORMAT) return d @classmethod def from_dict(cls, d): record = cls() for attr in record.traits(dictable=True): if attr == 'create_date': cd = d.get(attr) if cd and not isinstance(cd, datetime): cd = datetime.strptime(cd, DATE_FORMAT) record.create_date = cd else: try: setattr(record, attr, d.get(attr)) except TraitError: pass return record
class AllTypes(HasTraits): """ A simple class with all kinds of traits """ boolean_value = Bool(True, label="Custom Bool Label:") button_value = Button("I'm a button!") int_value = Int(42, tooltip="You can add a tooltip as well.") float_value = Float(3.141592) enum_value = Enum("foo", "bar", "baz", "qux") int_range_value = Range(low=0, high=10) float_range_value = Range(low=0.0, high=1.0) list_value = List([0, 1, 2]) str_value = Str("Word") date_value = Date(datetime.date.today()) time_value = Time(datetime.time()) range_value = Range(low=0, high=100, label="Traits Range Editor:", enaml_editor=DefaultEditor) _my_float = Float def _button_value_fired(self): print "Button was pressed" def _anytrait_changed(self, name, old, new): print name, "changed from", old, "to", new
class QuandlDataProvider(HasTraits): """ Very basic time serie generator. """ code = Str('NYX/XBRU_ABI') from_date = Date(today - datetime.timedelta(days=365)) to_date = Date(today) generate = Event timestamps = Property(depends_on='_resultset') data = Property(depends_on='_resultset') _resultset = Property(depends_on='generate') @cached_property def _get__resultset(self): results = Quandl.get(self.code, trim_start=self.from_date, trim_end=self.to_date, returns='numpy') return results @cached_property def _get_data(self): results = self._resultset # return the first time serie assuming the return results[results.dtype.names[1]] @cached_property def _get_timestamps(self): results = self._resultset # horry gorry conversion of the first column that we assume to be the # dates S10 and that we convert to M8[D] then to M8[s] days = results[results.dtype.names[0]].astype('datetime64[D]') seconds = days.astype('datetime64[s]') timestamps = seconds.astype(int) return timestamps ### Traits UI view ######################################################### traits_view = View(VGroup( HGroup('code'), HGroup('from_date', 'to_date'), HGroup(Spring(), Item('generate', editor=ButtonEditor(), show_label=False))), title='Generator', width=200, resizable=True)
class DateEditorDemo(HasTraits): """Demo class to show Date editors.""" single_date = Date() multi_date = List(Date) info_string = Str('The editors for Traits Date objects. Showing both ' 'the defaults, and one with alternate options.') multi_select_editor = DateEditor( allow_future=False, multi_select=True, shift_to_select=False, on_mixed_select='max_change', # Qt ignores these setting and always shows only 1 month: months=2, padding=30, ) traits_view = View( Item('info_string', show_label=False, style='readonly'), Group( Item('single_date', label='Simple date editor'), Item('single_date', style='custom', label='Default custom editor'), Item( 'single_date', style='readonly', editor=DateEditor( strftime='You picked %B %d %Y', message='Click a date above.', ), label='ReadOnly editor', ), label='Default settings for editors', ), Group( Item( 'multi_date', editor=multi_select_editor, style='custom', label='Multi-select custom editor', ), label='More customized editor: multi-select; disallow ' 'future; selection style; etc.', ), resizable=True, ) def _multi_date_changed(self): """Print each time the date value is changed in the editor.""" print(self.multi_date) def _simple_date_changed(self): """Print each time the date value is changed in the editor.""" print(self.simple_date, self.single_date) def _single_date_changed(self): """Print each time the date value is changed in the editor.""" print(self.single_date)
class Foo(HasTraits): dates = Dict() styles = Dict() fast_dates = List() slow_dates = List() current_date = Date() traits_view = View( Item( "current_date", style="custom", show_label=False, editor=StyledDateEditor( dates_trait="dates", styles_trait="styles" ), ) ) def __init__(self, *args, **kw): HasTraits.__init__(self, *args, **kw) self.styles = { "fast": CellFormat(bold=True, fgcolor="darkGreen"), "slow": CellFormat(italics=True, fgcolor="lightGray"), } self.fast_dates = [ date(2010, 7, 4), date(2010, 7, 3), date(2010, 7, 2), ] self.slow_dates = [ date(2010, 6, 28), date(2010, 6, 27), date(2010, 6, 24), ] @observe("fast_dates,slow_dates") def _update_dates_dict(self, event): self.dates["fast"] = self.fast_dates self.dates["slow"] = self.slow_dates def _current_date_changed(self, old, new): print("Old:", old, "New:", new)
class Image(HasTraits): """ An SEM image stored in a file. """ filename = File(exists=True) sample_id = Str() operator = Str("N/A") date_acquired = Date() scan_size = Tuple(Float, Float) scan_width = Float scan_height = Float image = Array(shape=(None, None), dtype='uint8') pixel_area = Float() def traits_init(self): # useful secondary attributes self.scan_width, self.scan_height = self.scan_size # Trait observers @observe('filename') def read_image(self, event): pil_image = PILImage.open(self.filename).convert("L") self.image = np.array(pil_image) @observe('scan_width, scan_height, image') def update_pixel_area(self, event): if self.image.size > 0: self.pixel_area = ( self.scan_height * self.scan_width / self.image.size ) else: self.pixel_area = 0 # Trait default methods def _date_acquired_default(self): return datetime.date.today() def _scan_size_default(self): return (1e-5, 1e-5)
class AllTypes(HasTraits): """ A simple class with all kinds of traits """ boolean_value = Bool(True, label="Custom Bool Label:") button_value = Button("I'm a button!") int_value = Int(42, tooltip="You can add a tooltip as well.") float_value = Float(3.141592) enum_value = Enum("foo", "bar", "baz", "qux") int_range_value = Range(low=0, high=10) float_range_value = Range(low=0.0, high=1.0) list_value = List([0, 1, 2]) str_value = Str("Word") date_value = Date(datetime.date.today()) time_value = Time(datetime.time()) range_value = Range(low=0, high=100, label="Traits Range Editor:", enaml_editor=DefaultEditor) _notifications = List(Tuple)
class Image(HasTraits): """ An SEM image stored in a file. """ filename = File(exists=True) sample_id = Str() date_acquired = Date() operator = Str("N/A") scan_size = Tuple(Float, Float) image = Array(shape=(None, None), dtype='uint8') def traits_init(self): # useful secondary attributes self.scan_width, self.scan_height = self.scan_size def _date_acquired_default(self): return datetime.datetime.today()
class HasDateTraits(HasStrictTraits): #: Simple case - no default, no parameters, no metadata simple_date = Date() #: Date with default epoch = Date(UNIX_EPOCH) #: Date with default provided via keyword. alternative_epoch = Date(default_value=NT_EPOCH) #: Datetime instances prohibited datetime_prohibited = Date(allow_datetime=False) #: Datetime instances allowed datetime_allowed = Date(allow_datetime=True) #: None prohibited none_prohibited = Date(allow_none=False) #: None allowed none_allowed = Date(allow_none=True) #: Strictly a non-None non-datetime date strict = Date(allow_datetime=False, allow_none=False)
class Person(HasTraits): """ A simple class representing a person object. """ # The last name of the person as a string last_name = Str # The first name of the person as a string first_name = Str # The date of birth of the person dob = Date(datetime.date(1970, 1, 1)) # The age of the person computed from their dob age = Property(Int, depends_on='dob') # This method is called when the age of the person needs to # be computed def _get_age(self): today = datetime.date.today() dob = self.dob delta = today - dob age = delta.days / 365 return age
class OptionValuation(HasTraits): # options parameters option_type = Enum(Put, Call) underlying = Float(36) strike = Float(40) dividend_yield = Range(0.0, 0.5) risk_free_rate = Range(0.0, 0.2) volatility = Range(0.0, 0.5) maturity = Date(datetime.date.today()) daycounter = Actual365Fixed() option_npv = Property( depends_on=[ 'option_type', 'underlying', 'strike', 'dividend_yield', 'risk_free_rate', 'volatility', 'maturity' ] ) ### Traits view ########################################################## traits_view = View( Item('option_type', editor=EnumEditor(values={Put:'Put', Call:'Call'})), 'underlying', 'strike', 'dividend_yield', 'risk_free_rate', 'volatility', 'maturity', HGroup( Item('option_npv', label='Option value')) ) ### Private protocol ##################################################### def _get_option_npv(self): """ Suboptimal getter for the npv. FIXME: We currently have to recreate most of the objects because we do not expose enough of the QuantLib api. """ # convert datetime object to QlDate maturity = QlDate.from_datetime(self.maturity) underlyingH = SimpleQuote(self.underlying) # bootstrap the yield/dividend/vol curves flat_term_structure = FlatForward( reference_date = settlement_date, forward = self.risk_free_rate, daycounter = self.daycounter ) flat_dividend_ts = FlatForward( reference_date = settlement_date, forward = self.dividend_yield, daycounter = self.daycounter ) flat_vol_ts = BlackConstantVol( settlement_date, calendar, self.volatility, self.daycounter ) black_scholes_merton_process = BlackScholesMertonProcess( underlyingH, flat_dividend_ts, flat_term_structure,flat_vol_ts ) payoff = PlainVanillaPayoff(self.option_type, self.strike) european_exercise = EuropeanExercise(maturity) european_option = VanillaOption(payoff, european_exercise) analytic_european_engine = AnalyticEuropeanEngine(black_scholes_merton_process) european_option.set_pricing_engine(analytic_european_engine) return european_option.net_present_value
class PlotCorr(HasTraits): data = Array() plot_type = Enum('CMap', 'Overlay', 'Vertical', 'Multiline') p_title = Str('Graph') x_lbl = Str('Time') y_lbl_type = Enum('Corr', 'Single', 'Custom') y_lbl = Str('Corr') y_labels = List(Str) scale_type = Enum('Time', 'default') first_day = Date() apply_btn = Button('Apply') save_btn = Button('Save') y_low = Float(100.0) y_high = Float(-1.0) multi_line_plot_renderer = Instance(MultiLinePlot) # Drives multi_line_plot_renderer.normalized_amplitude amplitude = Range(-20.0, 20.0, value=1) # Drives multi_line_plot_renderer.offset offset = Range(-15.0, 15.0, value=0) plot = Instance(Component) plot_vertical = Property(Instance(Component)) plot_overlay = Property(Instance(Component)) plot_cmap = Property(Instance(Component)) plot_multiline = Property(Instance(Component)) view = View(Tabbed( VGroup(Item('plot', editor=ComponentEditor(), width=600, height=400, show_label=False), Item('amplitude', label='amp', visible_when="plot_type=='Multiline'"), Item('offset', label='offset', visible_when="plot_type=='Multiline'"), Item('save_btn', show_label=False, width=200, height=100), label='Graph'), VGroup(Item('plot_type', style='custom'), Item('p_title', label='graph title'), Item('x_lbl', label='x axis label'), Item('y_lbl_type', style='custom'), Item('y_lbl', label='y axis label', visible_when="y_lbl_type=='Single'"), Item('y_labels', label='y axis labels', visible_when="y_lbl_type=='Custom'"), Item('scale_type', style='custom'), Item('first_day', enabled_when="scale_type=='Time'"), Item('apply_btn', show_label=False, width=200, height=100), label='Config', springy=True)), resizable=True) ########################################################################### # Protected interface. ########################################################################### def _create_dates(self, numpoints, start=None, units="days"): """ Returns **numpoints** number of dates that evenly bracket the current date and time. **units** should be one of "weeks", "days", "hours" "minutes", or "seconds". """ units_map = { "weeks": 7 * 24 * 3600, "days": 24 * 3600, "hours": 3600, "minutes": 60, "seconds": 1 } if start is None: start = time.time() # Now else: start = time.mktime(start.timetuple()) dt = units_map[units] dates = np.linspace(start, start + numpoints * dt, numpoints) return dates def _apply_btn_fired(self): self._update_plot() def _save_btn_fired(self): filter = 'PNG file (*.png)|*.png|\nTIFF file (*.tiff)|*.tiff|' dialog = FileDialog(action='save as', wildcard=filter) if dialog.open() != OK: return filename = dialog.path width, height = self.plot.outer_bounds gc = PlotGraphicsContext((width, height), dpi=100) gc.render_component(self.plot) try: gc.save(filename) except KeyError, e: errmsg = ("The filename must have an extension that matches " "a graphics format, such as '.png' or '.tiff'.") if str(e.message) != '': errmsg = ("Unknown filename extension: '%s'\n" % str(e.message)) + errmsg error(None, errmsg, title="Invalid Filename Extension")
class Foo(HasTraits): dates = List(Date) single_date = Date()
class TestClass(HasTraits): t = Date() x = Int()
class ExperimentType(HasTraits): """Defines the properties of the experiment.""" #========================================================================= # Important components #========================================================================= type = Instance(TypeSelector) shape = Instance(ShapeSelector, ()) reinforcement = Instance(ReinforcementSelector, ()) server_attributes = TypeSerieDialog() #========================================================================= # Attributes of the experiment #========================================================================= name = Str() start_date = Date() ldap_users = Instance(LDAPUsers, ()) record_mode = Bool(False) def __init__(self): self.start_date = datetime.today() self.fpath = join(experiment_dir, experiment_type_file) self.type = TypeSelector(parent=self) def update_series(self, experiment=None): if experiment == None: experiment = self.type.get_type() try: series = self.exp_model.update_series(experiment) except Exception: return [] self.type.update_series(series) return series def get_type_serie(self): return (self.type.get_type(), self.type.get_serie()) def get_user_serie_type(self): t = self.type.get_type() s = self.type.get_serie() if s == 'None': try: user, serie = self.server_attributes.open( self.ldap_users.users._get_options(), self.update_series(t)) except Exception: return None return (user, serie, t) def is_valid(self): if len(self.name) < 1: raise ValueError("Define a name for the experiment") def save(self): t = self.type.get_selected_value() s = self.type.get_serie() data = { 'name': self.name, 'ldap_users': self.ldap_users.get_user(), 'start_date': convert_date_to_string(self.start_date), 'type': t.type_name.lower(), 'type_data': t.save(), 'shape': self.shape.get_selected_key(), 'shape_data': self.shape.save(), 'reinforcement': self.reinforcement.save(), 'serie': s } with open(self.fpath, 'wb') as f: json.dump(data, f) return self.generate_file_name() def load(self): with open(self.fpath, 'r') as f: data = load(f) self.name = data['name'] self.start_date = convert_string_to_date(data['start_date']) user = data['ldap_users'] serie = data['serie'] t = data['type'] if serie == 'None': user, serie = self.server_attributes.open( self.ldap_users.users._get_options(), self.update_series(t)) self.reinforcement.load(data['reinforcement']) self.shape.load(data['shape_data']['shape']) self.ldap_users.show_user(user) self.type.set_serie(serie) self.type.load_type(data) @staticmethod def open(exp_model): experiment_type = ExperimentType() experiment_type.record_mode = True experiment_type.show_dialog = True experiment_type.exp_model = exp_model experiment_type.update_series() if experiment_type.configure_traits(kind='livemodal'): experiment_type.save() experiment_type.load() return True return False def generate_file_name(self): args = [ convert_date_to_string(self.start_date), self.name, self.ldap_users.get_user() ] return "{0}_{1}_{2}".format(*args) #========================================================================= # Traitsview + Traitsevent #========================================================================= show_dialog = Bool(False) ConfirmButton = Action(name="OK", enabled_when="not error", visible_when="show_dialog") view = View(VGroup(VGroup( Item('name'), Item('ldap_users', style='custom'), Item('start_date'), ), UItem('type', style='custom'), UItem('shape', style='custom'), UItem('reinforcement', style='custom'), enabled_when='record_mode'), buttons=[ConfirmButton])
class main_class(HasStrictTraits): value = Bounded(Date(date(2007, 12, 18)), date(2003, 12, 18), date(2010, 12, 18))
class Image(HasTraits): """ An SEM image stored in a file. """ filename = File(exists=True) sample_id = Str() operator = Str("N/A") date_acquired = Date() scan_size = Tuple(Float, Float) scan_width = Property(Float, depends_on='scan_size') scan_height = Property(Float, depends_on='scan_size') image = Array(shape=(None, None), dtype='uint8') histogram = Property(Array, depends_on='image') pixel_area = Float() # Trait observers @observe('filename') def read_image(self, event): pil_image = PILImage.open(self.filename).convert("L") self.image = np.array(pil_image) # compute some extra secondary attributes from the image if self.image.size > 0: self.pixel_area = (self.scan_height * self.scan_width / self.image.size) else: self.pixel_area = 0 # Trait default methods def _date_acquired_default(self): return datetime.date.today() def _scan_size_default(self): return (1e-5, 1e-5) # Trait property methods def _get_scan_width(self): return self.scan_size[0] def _set_scan_width(self, value): self.scan_size = (value, self.scan_size[1]) def _get_scan_height(self): return self.scan_size[1] def _set_scan_height(self, value): self.scan_size = (self.scan_size[0], value) @cached_property def _get_histogram(self): hist, bins = np.histogram( self.image, bins=256, range=(0, 256), density=True, ) return hist
class BoundedDate(Control): """ A base class for use with widgets that edit a Python datetime.date object bounded between minimum and maximum values. This class is not meant to be used directly. """ #: The minimum date available in the date edit. If not defined then #: the default value is September 14, 1752. Extra checks take place #: to make sure that the user does not programmatically set #: :attr:`min_date` > :attr:`max_date`. min_date = Property(Date, depends_on='_min_date') #: The internal min date storage _min_date = Date(date(1752, 9, 14)) #: The maximum date available in the date edit. If not defined then #: the default value is December 31, 7999. Extra checks take place #: to make sure that the user does not programmatically set #: :attr:`min_date` > :attr:`max_date`. max_date = Property(Date, depends_on='_max_date') #: The internal max date storage _max_date = Date(date(7999, 12, 31)) #: The currently selected date. Default is the current date. The #: value is bounded between :attr:`min_date` and :attr:`max_date`. #: Changing the boundary attributes might result in an update of #: :attr:`date` to fit in the new range. Attempts to assign a value #: outside of these bounds will result in a TraitError. date = Bounded(Date(date.today()), low='min_date', high='max_date') #: Overridden parent class trait abstract_obj = Instance(AbstractTkBoundedDate) #-------------------------------------------------------------------------- # Property methods #-------------------------------------------------------------------------- def _set_min_date(self, date): """ Set the min_date. Addtional checks are applied to make sure that :attr:`min_date` < :attr:`max_date` """ if date > self.max_date: msg = ("The minimum date should be smaller than the current " "maximum date({0}), but a value of {1} was given.") msg = msg.format(self.max_date, date) raise TraitError(msg) self._min_date = date self._adapt_date() def _set_max_date(self, date): """ Set the max_date. Addtional checks are applied to make sure that :attr:`min_date` < :attr:`max_date` """ if date < self.min_date: msg = ("The maximum date should be larger than the current " "minimum date({0}), but a value of {1} was given.") msg = msg.format(self.min_date, date) raise TraitError(msg) self._max_date = date self._adapt_date() def _get_max_date(self): """ The property getter for the maximum date. """ return self._max_date def _get_min_date(self): """ The property getter for the minimum date. """ return self._min_date def _adapt_date(self): """ Adapt the date to the bounderies """ self.date = min(max(self.date, self.min_date), self.max_date)
def __init__(self): super(TestDateTime, self).__init__() self.add_trait("in_1", Date(output=False)) self.add_trait("in_2", Time(output=False)) self.add_trait("out", List(output=True))
class Image(HasStrictTraits): """ An SEM image stored in a file. """ #: The filename of the image. filename = File(exists=True) #: The ID of the sample that is being imaged. sample_id = Str() #: The name of the operator who acquired the image. operator = Str("N/A") #: The date the image was acquired. date_acquired = Date() #: The size of the image. scan_size = Tuple(Float, Float) #: The width of the image. scan_width = Property(Float, depends_on='scan_size') #: The height of the image. scan_height = Property(Float, depends_on='scan_size') #: The image as a 2D numpy array image = Array(shape=(None, None), dtype='uint8') #: The area of each pixel. pixel_area = Property(Float, depends_on='scan_height,scan_width,image') #: The histogram of pixel intensities. histogram = Property(Array, depends_on='image') def threshold(self, low=0, high=255): """ Compute a threshold mask for the array. """ return (self.image >= low) & (self.image <= high) # Trait observers @observe('filename') def read_image(self, event): pil_image = PILImage.open(self.filename).convert("L") self.image = np.array(pil_image) # Trait default methods def _date_acquired_default(self): return datetime.date.today() def _scan_size_default(self): return (1e-5, 1e-5) # Trait property methods def _get_scan_width(self): return self.scan_size[0] def _set_scan_width(self, value): self.scan_size = (value, self.scan_size[1]) def _get_scan_height(self): return self.scan_size[1] def _set_scan_height(self, value): self.scan_size = (self.scan_size[0], value) def _get_pixel_area(self): if self.image.size > 0: return self.scan_height * self.scan_width / self.image.size else: return 0 @cached_property def _get_histogram(self): hist, bins = np.histogram( self.image, bins=256, range=(0, 256), density=True, ) return hist
class BoundedDate(Control): """ A base class for components which edit a Python datetime.date object bounded between minimum and maximum values. This class is not meant to be used directly. """ #: The minimum date available in the date edit. If not defined then #: the default value is September 14, 1752. minimum = Property(Date, depends_on ='_minimum') #: The internal minimum date storage _minimum = Date(py_date(1752, 9, 14)) #: The maximum date available in the date edit. If not defined then #: the default value is December 31, 7999. maximum = Property(Date, depends_on ='_maximum') #: The internal maximum date storage _maximum = Date(py_date(7999, 12, 31)) #: The currently selected date. Default is the current date. The #: value is bounded between :attr:`minimum` and :attr:`maximum`. date = Bounded(Date(py_date.today()), low='minimum', high='maximum') #-------------------------------------------------------------------------- # Initialization #-------------------------------------------------------------------------- def snapshot(self): """ Return a dictionary which contains all the state necessary to initialize a client widget. """ snap = super(BoundedDate, self).snapshot() snap['minimum'] = self.minimum.isoformat() snap['maximum'] = self.maximum.isoformat() snap['date'] = self.date.isoformat() return snap def bind(self): """ A method called after initialization which allows the widget to bind any event handlers necessary. """ super(BoundedDate, self).bind() otc = self.on_trait_change otc(self._send_minimum, 'minimum') otc(self._send_maximum, 'maximum') otc(self._send_date, 'date') #-------------------------------------------------------------------------- # Message Handling #-------------------------------------------------------------------------- def on_action_date_changed(self, content): """ Handle the 'date_changed' action from the UI control. """ date = parse_iso_dt(content['date']).date() self.set_guarded(date=date) def _send_minimum(self): """ Send the minimum date to the client widget. """ content = {'minimum': self.minimum.isoformat()} self.send_action('set_minimum', content) def _send_maximum(self): """ Send the maximum date to the client widget. """ content = {'maximum': self.maximum.isoformat()} self.send_action('set_maximum', content) def _send_date(self): """ Send the current date to the client widget. """ if 'date' not in self.loopback_guard: content = {'date': self.date.isoformat()} self.send_action('set_date', content) #-------------------------------------------------------------------------- # Property methods #-------------------------------------------------------------------------- def _get_minimum(self): """ The property getter for the minimum date. """ return self._minimum def _set_minimum(self, date): """ The property setter for the minimum date. If the new minimum is greater than the current maximum, then the maximum will be adjusted up. """ if date > self._maximum: self._maximum = date self._minimum = date def _get_maximum(self): """ The property getter for the maximum date. """ return self._maximum def _set_maximum(self, date): """ The property setter for the maximum date. If the new maximum is less than the current minimum, then the minimum will be ajusted down. """ if date < self._minimum: self._minimum = date self._maximum = date #-------------------------------------------------------------------------- # Private API #-------------------------------------------------------------------------- @on_trait_change('minimum, maximum') def _adapt_date(self): """ Actively adapt the date to lie within the boundaries. """ self.date = min(max(self.date, self.minimum), self.maximum)
class ExpBase(SimDBClass): production_date = Date(simdb = True) testing_date = Date(simdb = True)