Desktopové prostředí KDE Plasma bylo vydáno ve verzi 6.5 (Mastodon). Přehled novinek i s videi a se snímky obrazovek v oficiálním oznámení. Podrobný přehled v seznamu změn.
Rodina jednodeskových počítačů Orange Pi se rozrostla (𝕏) o Orange Pi 6 Plus.
Na Humble Bundle běží akce Humble Tech Book Bundle: All Things Raspberry Pi by Raspberry Pi Press. Se slevou lze koupit elektronické knihy od nakladatelství Raspberry Pi Press a podpořit Raspberry Pi Press, Raspberry Pi Foundation North America nebo Humble.
Přidaný režim autonomního řízení vozidel Tesla Mad Max je dostupný pro vybrané zákazníky v programu EAP (Early Access Program). Nový režim je na silnici agresivnější, častěji mění pruhy a ne vždy dodržuje rychlostní limity. Agentura JPP spekuluje, že v Česku by se mohl nový režim namísto Mad Max jmenovat Mad Turek...
Byla vydána nová verze 9.18 z Debianu vycházející linuxové distribuce DietPi pro (nejenom) jednodeskové počítače. Nově také pro NanoPi R3S, R3S LTS, R76S a M5. Přehled novinek v poznámkách k vydání.
bat, tj. vylepšený cat se zvýrazňováním syntaxe a integrací s gitem, byl vydán ve verzi 0.26.0.
Byla vydána první verze 0.0.1 [Mastodon] multipatformního renderovacího jádra webového prohlížeče Servo (Wikipedie). Vývoj Serva započal v roce 2012 v Mozilla Corporation. V roce 2020 bylo Servo předáno nadaci Linux Foundation. Servo je napsané v programovacím jazyce Rust.
Cloudovou službu Amazon Web Services (AWS) americké firmy Amazon dnes postihl globální výpadek. Omezil dostupnost řady aplikací a webů, například populární platformu Snapchat nebo aplikaci s prvky umělé inteligence (AI) Perplexity. Podle webu Downdetector hlásily problémy také uživatelé obchodu Amazon, streamovací platformy PrimeVideo nebo platební služby PayPal.
GNU Octave lze nově používat ve webovém prohlížeči v JupyterLite s jádrem Xeus-Octave.
Od 3. do 16. listopadu proběhnou Dny AI 2025. V úterý 11. listopadu proběhne Open source AI day v Red Hatu v Brně.
Pro jeden Pythoní projekt na kterém pracuji jsem potřeboval převést CRONový zápis (12 9 * * *) na "human readable" string, zde se chci podělit o výsledek.
Po chvilce hledání na google jsem zjistil že nic takového pro Python neexistuje (nebo je projekt ve velmi raném/nepoužitelném stádiu). Po prvních pokusech a zjištění ze to kvůli hromadě vyjímek nebude jen pár řádek kódu, mě napadlo že bych se mohl podívat zda li tohle již někdo neřešil pro jiné jazyky. Nakonec jsem narazil na celkem slušnou .NET implementaci (Rozluštění záhady proč někdo tvoří parser na UNIXový CRON v .NETu necháme pro Akta X) kterou jsem se rozhodl naportovat do Pythonu (+ pár menších vylepšení).
cron-descriptor je dostupný skrze pip:
(pokud zde mate velke bile misto, tak pokracovani je nize pod pravym sidebarem... nevim jak tento bug z me strany opravit)
pip install cron-descriptor
from cron_descriptor import Options, CasingTypeEnum, DescriptionTypeEnum, ExpressionDescriptor # Jednoduše print(ExpressionDescriptor("*/10 * * * *")) # Pokročilé nastavení (viz Options.py) descripter = ExpressionDescriptor("*/10 * * * *", throw_exception_on_parse_error = True, casing_type = CasingTypeEnum.Sentence, use_24hour_time_format = True) # get_description uses DescriptionTypeEnum.FULL by default: print(descripter.get_description()) # Nebo print("{}".format(descripter))
# 24 hodinový formát 17 * * * * -> At 17 minutes past the hour 25 6 * * * -> At 06:25 47 6 * * 7 -> At 06:47, only on Saturday 52 6 1 * * -> At 06:52, on day 1 of the month # 12 hodinový formát 17 * * * * -> At 17 minutes past the hour 25 6 * * * -> At 06:25 AM 47 6 * * 7 -> At 06:47 AM, only on Saturday 52 6 1 * * -> At 06:52 AM, on day 1 of the month
https://github.com/Salamek/cron-descriptor
PR's jsou vítány
Tiskni
Sdílej:
Pristup prepsat existujici implementaci v jinem jazyce je urcite mnohem lepsi nez zacinat od nuly.Ale je to menší zábava (respekt autorovi).
Podpora Pythonu 2.7-3.4Jak je toho dosaženo? Dle zdrojaku mám dojem, že se prostě nepoužívá žádná kolizní syntaxe. Jak se to dá řešit?
#: ExpressionDescriptor.py:218 #, python-brace-format msgid "at {0}" msgstr "v {0}"Pokud by stejným stylem bylo udělaných vět více, může být v některých použita špatná předložka. Letmý pohled do slovníku rychle ukáže, kolik možností překladu podle kontextu se nabízí – úryvek ze slovnik.cz:
at - k at - na (místo, čas, stav, pohyb, cíl) at - po (cena, množství, např.o ceně k)s at - v (místo, čas, stav) at - z at - u (těsně) at - o (čas, stav) at - při (čas, stav, činnost) at - za (čas, stav) at - alespoň at - jak budete mít čas at - jak to je at - ke at - těsně u (2. p.) at - veSprávný přístup je mít jeden řetězec s celou větou se zástupnými symboly a tu přeložit. Nikoliv slepovat krátké samostatně překládané řetězce do věty s anglickým slovosledem. Naneštěstí v tomto případě to je tak trochu pointa celého toho programu. Dalo by se to zlepšit použitím delších fragmentů, ale ani to ideální nebude. Proto například Osmand má hlasovou navigaci implementovanou v Prologu a každý jazyk má vlastní pravidla, jak skládat věty pro různá oznámení. Pak můžeš mít správně slovosled podle daného jazyka, ale i skloňování, časování a další vymoženosti.
Nedávno som niečo podobné robil pre recurrence rule a podobných problémov je tam dosť veľa a časť z nich je rovnaká pre všetky projekty ktoré vyjadrujú čas/dátum v ľudsky zrozumiteľnom tvare (ak má ísť naozaj o tvar, ktorému majú bez problémov rozumieť ľudia).Vždycky když něco takového čtu, tak si říkám, že asi nejsem člověk. Nejlépe se mi používá tvar, který víceméně standardizuje ISO. Všechno vyjádřeno číselně. Všechna čísla doplněná zleva nulami do jednotného zarovnání. Všechna čísla seřazena podle váhy od největší po nejmenší. Paradoxně je takový způsob ze všech řetězcových zápisů nejvýhodnější i pro počítač.
To "on day 1 of the month", s prižmúrením očí, dáva v angličtine zmysel, ale český preklad "v 1 den v měsíci" má iný význam.To bude asi reakce na úplně jiný komentář.
PS: A len tak pre zaujímavosť, ako by vyzeralo vyjadrenie crontab v "ISO" formáte (a prípadne aj s príkladom pre recurrence rule).Oni definují formát data a času. Musel bys tam doplnit nějaké ty zápisy s crontab. Já osobně nemám problém používat crontab zápis tak jak je, bez nějakých přepisů.
""" Converts a Cron Expression into a human readable string """ class ExpressionDescriptor(object): m_special_characters = ['/', '-', ',', '*'] m_expression = '' m_options = None m_expression_parts = [] m_parsed = FalseProč jsi použil tyhle divné docstringy? V pythonu bývá zvykem používat jako docstring první řetězec v těle funkce. Ty používáš všechny před tělem funkce. Nápověda tak nefunguje:
bystrousak:~/Plocha/cron-descriptor,0$ python Python 2.7.6 (default, Jun 22 2015, 17:58:13) [GCC 4.8.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> from cron_descriptor.ExpressionDescriptor import ExpressionDescriptor >>> help(ExpressionDescriptor)
Help on class ExpressionDescriptor in module cron_descriptor.ExpressionDescriptor: class ExpressionDescriptor(__builtin__.object) | Methods defined here: | | __init__(self, expression, options=None, **kwargs) | | __repr__(self) | | __str__(self) | | format_time(self, hour_expression, minute_expression, second_expression='') | | get_day_of_month_description(self) | | get_day_of_week_description(self) | | get_description(self, type=1) | | get_full_description(self) | | get_hours_description(self)Správně by to mělo vypadat takhle:
class ExpressionDescriptor(object): """ Converts a Cron Expression into a human readable string """ m_special_characters = ['/', '-', ',', '*'] m_expression = '' m_options = None m_expression_parts = [] m_parsed = FalseCož pak v help()u vypadá:
Help on class ExpressionDescriptor in module cron_descriptor.ExpressionDescriptor: class ExpressionDescriptor(__builtin__.object) | Converts a Cron Expression into a human readable string | | Methods defined here:Nejde o problém jen u interní funkce help(), ale i různých nápověd v IDE a generování dokumentace. Když už se s tou dokumentací píšeš, tak mi přijde docela škoda jí takhle „zahodit“. Pak taky vidím, že používáš vlastní Enum:
class DescriptionTypeEnum(object): FULL = 1 TIMEOFDAY = 2 SECONDS = 3 MINUTES = 4 HOURS = 5 DAYOFWEEK = 6 MONTH = 7 DAYOFMONTH = 8 YEAR = 9Což by pro budoucí úpravy bylo lepší zapsat spíš jako:
class DescriptionTypeEnum(object): _cnt = (x for x in range(100)) FULL = next(_cnt) TIMEOFDAY = next(_cnt) SECONDS = next(_cnt) MINUTES = next(_cnt) HOURS = next(_cnt) DAYOFWEEK = next(_cnt) MONTH = next(_cnt) DAYOFMONTH = next(_cnt) YEAR = next(_cnt)Není to sice nutnost, ale může ti to ušetřit nepříjemné bugy, protože se to stará o unikátnost hodnoty. Potom tohle
if type == DescriptionTypeEnum.FULL: description = self.get_full_description() elif type == DescriptionTypeEnum.TIMEOFDAY: description = self.get_time_of_day_description() elif type == DescriptionTypeEnum.HOURS: description = self.get_hours_description() elif type == DescriptionTypeEnum.MINUTES: description = self.get_minutes_description() elif type == DescriptionTypeEnum.SECONDS: description = self.get_seconds_description() elif type == DescriptionTypeEnum.DAYOFMONTH: description = self.get_day_of_month_description() elif type == DescriptionTypeEnum.MONTH: description = self.get_month_description() elif type == DescriptionTypeEnum.DAYOFWEEK: description = self.get_day_of_week_description() elif type == DescriptionTypeEnum.YEAR: description = self.get_year_description() else: description = self.get_seconds_description()By bylo asi elegantněji zapsáno jako:
choices = { DescriptionTypeEnum.FULL: self.get_full_description, DescriptionTypeEnum.TIMEOFDAY: self.get_time_of_day_description, DescriptionTypeEnum.HOURS: self.get_hours_description, DescriptionTypeEnum.MINUTES: self.get_minutes_description, DescriptionTypeEnum.SECONDS: self.get_seconds_description, DescriptionTypeEnum.DAYOFMONTH: self.get_day_of_month_description, DescriptionTypeEnum.MONTH: self.get_month_description, DescriptionTypeEnum.DAYOFWEEK: self.get_day_of_week_description, DescriptionTypeEnum.YEAR: self.get_year_description, } description = choices.get(type, self.get_seconds_description)()Nehledě tedy na to, že si tím názvem proměnné shadowuješ interní funkci type().
for i in range(0, len(hour_parts)):Range jede vždy od nuly. Sice to ničemu nevadí, ale ani to nic nepřidává.
if len(description) > 0:Obecně všechny tyhle kontroly se dají přepsat na elegantnější
if description:Tohle
return self.get_segment_description(self.m_expression_parts[0], _("every second"), lambda s: s.zfill(2), lambda s: _( "every {0} seconds").format(s), lambda s: _( "seconds {0} through {1} past the minute"), lambda s: _("at {0} seconds past the minute"))by asi vypadalo podstatně líp, kdybys to rozepsal takhle:
return self.get_segment_description( self.m_expression_parts[0], _("every second"), lambda s: s.zfill(2), lambda s: _("every {0} seconds").format(s), lambda s: _("seconds {0} through {1} past the minute"), lambda s: _("at {0} seconds past the minute") )Já vím, je to čistě otázka vkusu, ale fakt mi to přijde podstatně čitelnější a nemusíš pak zbytečně zalamovat ty výrazy, protože se ti nevešly na konec řádku. Asi by se toho našlo víc, tohle mě napadlo jen tak v rychlosti.
for i in range(0, len(hour_parts)): ... hour_parts[i] ...je lepší (pythoničtější) psát:
for i, hour_part in enumerate(hour_parts): ... hour_part ...
Jo a misto psani sem jsi mohl rovnou udelat fork a poslat PRNerad dělám stylistické pull requesty, protože nemusí být začleněny, protože se ti něco nemusí líbit. Pak je to kopa práce k ničemu. Tohle byly spíš rady, než že by šlo o něco podstatného.![]()
Já se v takových případech zeptám Googlu, jsou stránky kde není problém naklikat si chování a vyplivne to zápis pro CRON. Nevím ale jistě jestli to jde i obráceně, tedy vložit a nechat si vypsat co se bude dít
Zrovna konfigurator CRONu se da napsat tak aby uzivatel nic nerozbyl... protoze se tam dostane jen to co tam sam v te aplikaci pustis...To ovšem pak není konfigurátor cronu, ale custom plánovač na vybrané akce. Jestli na spouštění úloh používá vlastní proces nebo cron je jen implementační detail. Webhosting tady asi řešit nebudeme. :)