Open source softwarový stack ROCm (Wikipedie) pro vývoj AI a HPC na GPU od AMD byl vydán ve verzi 7.0.0. Přidána byla podpora AMD Instinct MI355X a MI350X.
Byla vydána nová verze 258 správce systému a služeb systemd (GitHub).
Byla vydána Java 25 / JDK 25. Nových vlastností (JEP - JDK Enhancement Proposal) je 18. Jedná se o LTS verzi.
Věra Pohlová před 26 lety: „Tyhle aféry každého jenom otravují. Já bych všechny ty internety a počítače zakázala“. Jde o odpověď na anketní otázku deníku Metro vydaného 17. září 1999 na téma zneužití údajů o sporožirových účtech klientů České spořitelny.
Byla publikována Výroční zpráva Blender Foundation za rok 2024 (pdf).
Byl vydán Mozilla Firefox 143.0. Přehled novinek v poznámkách k vydání a poznámkách k vydání pro vývojáře. Nově se Firefox při ukončování anonymního režimu zeptá, zda chcete smazat stažené soubory. Dialog pro povolení přístupu ke kameře zobrazuje náhled. Obzvláště užitečné při přepínání mezi více kamerami. Řešeny jsou rovněž bezpečnostní chyby. Nový Firefox 143 bude brzy k dispozici také na Flathubu a Snapcraftu.
Byla vydána betaverze Fedora Linuxu 43 (ChangeSet), tj. poslední zastávka před vydáním finální verze, která je naplánována na úterý 21. října.
Multiplatformní emulátor terminálu Ghostty byl vydán ve verzi 1.2 (𝕏, Mastodon). Přehled novinek, vylepšení a nových efektů v poznámkách k vydání.
Byla vydána nová verze 4.5 (𝕏, Bluesky, Mastodon) multiplatformního open source herního enginu Godot (Wikipedie, GitHub). Přehled novinek i s náhledy v příspěvku na blogu.
Byla vydána verze 3.0 (Mastodon) nástroje pro záznam a sdílení terminálových sezení asciinema (GitHub). S novou verzí formátu záznamu asciicast v3, podporou live streamingu a především kompletním přepisem z Pythonu do Rustu.
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. :)