def _validate(self, value): if len(value) not in (3, 6): raise ValidationError(_("Color length must be 3 or 6 characters")) for val in value: if val not in string.hexdigits: raise ValidationError( _("Color value must contain only valid hexadecimal color " "codes (numbers or letters between 'A' end 'F')")) super()._validate(value)
class IPygmentsCodeConfiguration(Interface): """Pygments html formatter options""" lexer = Choice(title=_("Selected lexer"), description=_("Lexer used to format source code"), required=True, vocabulary=PYGMENTS_LEXERS_VOCABULARY_NAME, default='auto') display_linenos = Bool( title=_("Display line numbers?"), description=_("If 'no', line numbers will be hidden"), required=True, default=True) disable_wrap = Bool( title=_("Lines wrap?"), description=_( "If 'yes', lines wraps will be enabled; line numbers will " "not be displayed if lines wrap is enabled..."), required=True, default=False) style = Choice(title=_("Color style"), description=_("Selected color style"), required=True, vocabulary=PYGMENTS_STYLES_VOCABULARY_NAME, default='default')
def get_age(value, request=None): """Get 'human' age of a given datetime (including timezone) compared to current datetime (in UTC) :param datetime value: input datetime to be compared with current datetime :return: str; the delta value, converted to months, weeks, days, hours or minutes >>> from datetime import datetime, timedelta >>> from pyams_utils.date import get_age >>> now = datetime.utcnow() >>> get_age(now) 'less than 5 minutes ago' >>> get_age(now - timedelta(minutes=10)) '10 minutes ago' >>> get_age(now - timedelta(hours=2)) '2 hours ago' >>> get_age(now - timedelta(days=1)) 'yesterday' >>> get_age(now - timedelta(days=2)) 'the day before yesterday' >>> get_age(now - timedelta(days=4)) '4 days ago' >>> get_age(now - timedelta(weeks=2)) '2 weeks ago' >>> get_age(now - timedelta(days=80)) '3 months ago' >>> get_age(None) '--' """ if not value: return '--' if request is None: request = check_request() translate = request.localizer.translate now = gmtime(datetime.utcnow()) delta = now - gmtime(value) if delta.days > 60: result = translate(_("%d months ago")) % int( round(delta.days * 1.0 / 30)) elif delta.days > 10: result = translate(_("%d weeks ago")) % int(round( delta.days * 1.0 / 7)) elif delta.days > 2: result = translate(_("%d days ago")) % delta.days elif delta.days == 2: result = translate(_("the day before yesterday")) elif delta.days == 1: result = translate(_("yesterday")) else: # less than one day hours = int(round(delta.seconds * 1.0 / 3600)) if hours > 1: result = translate(_("%d hours ago")) % hours elif delta.seconds > 300: result = translate(_("%d minutes ago")) % int( round(delta.seconds * 1.0 / 60)) else: result = translate(_("less than 5 minutes ago")) return result
class TextRenderer(BaseHTMLRenderer): """Basic text HTML renderer This renderer only replace newlines with HTML breaks. """ label = _("Simple text") def render(self, **kwargs): return html.escape(self.context).replace('\n', '<br />\n')
class IInheritInfo(ILocation): """Inheritance info""" target_interface = Attribute("Parent target interface") adapted_interface = Attribute("Context or parent adapted interface") parent = Attribute("First parent supporting target interface") can_inherit = Attribute("Can inherit from parent?") inherit = Bool(title=_("Inherit from parent"), required=False, default=True) no_inherit = Bool(title=_("Don't inherit from parent"), required=False, default=False) inherit_from = Attribute( "Parent from which adapted interface is inherited")
class MarkdownTextRenderer(BaseHTMLRenderer): """Markdown HTML renderer This renderer is converting *Markdown* formatted text to HTML. """ label = _("Markdown text") def render(self, **kwargs): """Render Markdown code to HTML""" return markdown(self.context)
def get_human_size(value, request=None): """Convert given bytes value in human readable format """ if request is None: request = check_request() translate = request.localizer.translate try: locale = Locale(request.locale_name) except UnknownLocaleError: locale = Locale( request.registry.settings.get('pyramid.default_locale_name', 'en')) if value < 1024: return format_decimal(value, translate(_('0 bytes')), locale) value /= 1024 if value < 1024: return format_decimal(value, translate(_('0.# Kb')), locale) value /= 1024 if value < 1024: return format_decimal(value, translate(_('0.0# Mb')), locale) value /= 1024 return format_decimal(value, translate(_('0.0## Gb')), locale)
class IHTMLRenderer(Interface): """Text renderer interface HTML renderers are implemented as adapters for a source object (which can be a string) and a request, so that you can easily implement custom renderers for any object and/or for any request layer. """ label = Attribute(_("Optional renderer label")) def render(self, **kwargs): """Render adapted text"""
def __init__(self, context): # pylint: disable=unused-argument terms = [SimpleTerm('auto', title=_("Automatic detection"))] # pylint: disable=unused-variable for name, aliases, filetypes, mimetypes in sorted( unique_iter(get_all_lexers(), key=lambda x: x[0].lower()), key=lambda x: x[0].lower()): terms.append( SimpleTerm(aliases[0] if len(aliases) > 0 else name, title='{0}{1}'.format( name, ' ({})'.format(', '.join(filetypes)) if filetypes else ''))) super().__init__(terms)
class SourceCodeTextRenderer(BaseHTMLRenderer): """Source code HTML renderer This renderer is converting source code to HTML. """ label = _("Source code") def render(self, **kwargs): """Render source code to HTML""" settings = kwargs.get('settings') if not settings: settings = PygmentsCodeRendererSettings() return render_source(self.context, settings)
class ReStructuredTextRenderer(BaseHTMLRenderer): """reStructuredText HTML renderer This renderer is using *docutils* to convert text to HTML output. """ label = _("ReStructured text") def render(self, **kwargs): """Render reStructuredText to HTML""" overrides = { 'halt_level': 6, 'input_encoding': 'unicode', 'output_encoding': 'unicode', 'initial_header_level': 3, } if 'settings' in kwargs: overrides.update(kwargs['settings']) parts = docutils.core.publish_parts(self.context, writer_name='html', settings_overrides=overrides) return ''.join((parts['body_pre_docinfo'], parts['docinfo'], parts['body']))
class DateRangeSchema(TupleSchema): """Dates range schema type""" after = SchemaNode(Date(), title=_("Range beginning date"), missing=null) before = SchemaNode(Date(), title=_("Range ending date (excluded)"), missing=null)
class InvalidEmail(ValidationError): """Invalid email validation error""" __doc__ = _( "Email address must be entered as « [email protected] », without '<' and '>' characters" )
class IZEOConnection(Interface): """ZEO connection settings interface""" name = TextLine(title=_("Connection name"), description=_("Registration name of ZEO connection"), required=True) server_name = TextLine(title=_("ZEO server name"), description=_("Hostname of ZEO server"), required=True, default='localhost') server_port = Int(title=_("ZEO server port"), description=_("Port number of ZEO server"), required=True, default=8100) storage = TextLine(title=_("ZEO server storage"), description=_("Storage name on ZEO server"), required=True, default='1') username = TextLine( title=_("ZEO user name"), description=_( "User name on ZEO server; only for ZEO server before 5.0"), required=False) password = Password(title=_("ZEO password"), description=_( "User password on ZEO server; only for ZEO server " "before 5.0"), required=False) server_realm = TextLine( title=_("ZEO server realm"), description=_( "Realm name on ZEO server; only for ZEO server before 5.0"), required=False) blob_dir = TextLine(title=_("BLOBs directory"), description=_("Directory path for blob data"), required=False) shared_blob_dir = Bool( title=_("Shared BLOBs directory ?"), description=_( "Flag whether the blob_dir is a server-shared filesystem " "that should be used instead of transferring blob data over zrpc." ), required=True, default=False) connection = Attribute("Current ZEO connection") def get_settings(self): """Get ZEO connection setting as a JSON dict""" def update(self, settings): """Update internal fields with given settings dict""" def get_connection(self, wait_timeout=30, get_storage=False): """Open ZEO connection with given settings"""
from zope.interface import Interface from zope.schema.interfaces import ConstraintNotSatisfied, InvalidDottedName, InvalidId, \ InvalidURI, InvalidValue, NotAContainer, NotAnIterator, NotUnique, RequiredMissing, \ SchemaNotFullyImplemented, SchemaNotProvided, TooBig, TooLong, TooShort, TooSmall, Unbound, \ WrongContainedType, WrongType __docformat__ = 'restructuredtext' from pyams_utils import _ # # Custom zope.schema exceptions messages # WrongContainedType.__doc__ = _("""Wrong contained type""") NotUnique.__doc__ = _("""One or more entries of sequence are not unique.""") SchemaNotFullyImplemented.__doc__ = _("""Schema not fully implemented""") SchemaNotProvided.__doc__ = _("""Schema not provided""") InvalidURI.__doc__ = _("""The specified URI is not valid.""") InvalidId.__doc__ = _("""The specified id is not valid.""") InvalidDottedName.__doc__ = _("""The specified dotted name is not valid.""") Unbound.__doc__ = _("""The field is not bound.""") RequiredMissing.__doc__ = _("""Required input is missing.""") WrongType.__doc__ = _("""Object is of wrong type.""") TooBig.__doc__ = _("""Value is too big""") TooSmall.__doc__ = _("""Value is too small""") TooLong.__doc__ = _("""Value is too long""") TooShort.__doc__ = _("""Value is too short""") InvalidValue.__doc__ = _("""Invalid value""")
class StringListSchema(SequenceSchema): """Strings list list""" value = SchemaNode(String(), title=_("Item value"), missing=drop)
class IServerTimezone(Interface): """Server timezone interface""" timezone = TimezoneField(title=_("Server timezone"), description=_("Default server timezone"), required=True)
def get_duration(first, last=None, request=None): # pylint: disable=too-many-branches """Get 'human' delta as string between two dates :param datetime|timedelta first: start date :param datetime last: end date, or current date (in UTC) if None :param request: the request from which to extract localization infos :return: str; approximate delta between the two input dates >>> from datetime import datetime, timedelta >>> from pyams_utils.date import get_duration >>> from pyramid.testing import DummyRequest Let's try with a provided timedelta: >>> duration = timedelta(seconds=20) >>> get_duration(duration) '20 seconds' >>> date1 = datetime(2015, 1, 1) >>> date2 = datetime(2014, 3, 1) >>> get_duration(date1, date2) '10 months' Dates order is not important: >>> get_duration(date2, date1) '10 months' >>> date2 = datetime(2014, 11, 10) >>> get_duration(date1, date2) '7 weeks' >>> date2 = datetime(2014, 12, 26) Let's try with a requuest: >>> request = DummyRequest() >>> get_duration(date1, date2, request) '6 days' For durations lower than 2 days, duration also display hours: >>> date1 = datetime(2015, 1, 1) >>> date2 = datetime(2015, 1, 2, 15, 10, 0) >>> get_duration(date1, date2, request) '1 day and 15 hours' >>> date2 = datetime(2015, 1, 2) >>> get_duration(date1, date2, request) '24 hours' >>> date2 = datetime(2015, 1, 1, 13, 12) >>> get_duration(date1, date2, request) '13 hours' >>> date2 = datetime(2015, 1, 1, 1, 15) >>> get_duration(date1, date2, request) '75 minutes' >>> date2 = datetime(2015, 1, 1, 0, 0, 15) >>> get_duration(date1, date2, request) '15 seconds' >>> now = datetime.utcnow() >>> delta = now - date1 >>> get_duration(date1, None, request) == '%d months' % int(round(delta.days * 1.0 / 30)) True """ if isinstance(first, timedelta): delta = first else: if last is None: last = datetime.utcnow() assert isinstance(first, datetime) and isinstance(last, datetime) first, last = min(first, last), max(first, last) delta = last - first if request is None: request = check_request() translate = request.localizer.translate if delta.days > 60: result = translate(_("%d months")) % int(round(delta.days * 1.0 / 30)) elif delta.days > 10: result = translate(_("%d weeks")) % int(round(delta.days * 1.0 / 7)) elif delta.days >= 2: result = translate(_("%d days")) % delta.days else: hours = int(round(delta.seconds * 1.0 / 3600)) if delta.days == 1: if hours == 0: result = translate(_("24 hours")) else: result = translate( _("%d day and %d hours")) % (delta.days, hours) else: if hours > 2: result = translate(_("%d hours")) % hours else: minutes = int(round(delta.seconds * 1.0 / 60)) if minutes > 2: result = translate(_("%d minutes")) % minutes else: result = translate(_("%d seconds")) % delta.seconds return result
class IIndexLength(Interface): """Index length interface""" count = Int(title=_("Indexed elements count"), readonly=True)
>>> value = datetime(2016, 11, 15, 10, 13, 12) >>> value datetime.datetime(2016, 11, 15, 10, 13, 12) >>> date_to_datetime(value) is value True >>> date_to_datetime(None) is None True """ if not value: return None if isinstance(value, datetime): return value return datetime(value.year, value.month, value.day) SH_DATE_FORMAT = _("%d/%m/%Y") SH_DATETIME_FORMAT = _("%d/%m/%Y - %H:%M") EXT_DATE_FORMAT = _("on %d/%m/%Y") EXT_DATETIME_FORMAT = _("on %d/%m/%Y at %H:%M") def format_date(value, format_string=EXT_DATE_FORMAT, request=None): """Format given date with the given format :param datetime value: the value to format :param str format_string: a format string to use by `strftime` function :param request: the request from which to extract localization info for translation :return: str; input datetime converted to given format >>> from datetime import datetime