Alyssa Rosenzweig se v příspěvku na svém blogu Vulkan 1.3 na M1 za 1 měsíc rozepsala o novém Vulkan 1.3 ovladači Honeykrisp pro Apple M1 splňujícím specifikaci Khronosu. Vychází z ovladače NVK pro GPU od Nvidie. V plánu je dále rozchodit DXVK a vkd3d-proton a tím pádem Direct3D, aby na Apple M1 s Asahi Linuxem běžely hry pro Microsoft Windows.
Byla vydána (𝕏) květnová aktualizace aneb nová verze 1.90 editoru zdrojových kódů Visual Studio Code (Wikipedie). Přehled novinek i s náhledy a animovanými gify v poznámkách k vydání. Ve verzi 1.90 vyjde také VSCodium, tj. komunitní sestavení Visual Studia Code bez telemetrie a licenčních podmínek Microsoftu.
Byla vydána (Mastodon, 𝕏) nová verze 2024.2 linuxové distribuce navržené pro digitální forenzní analýzu a penetrační testování Kali Linux (Wikipedie). Přehled novinek se seznamem nových nástrojů v oficiálním oznámení.
Počítačová hra Tetris slaví 40 let. Alexej Pažitnov dokončil první hratelnou verzi 6. června 1984. Mezitím vznikla celá řada variant. Například Peklo nebo Nebe. Loni měl premiéru film Tetris.
MicroPython (Wikipedie), tj. implementace Pythonu 3 optimalizovaná pro jednočipové počítače, byl vydán ve verzi 1.23.0. V přehledu novinek je vypíchnuta podpora dynamických USB zařízení nebo nové moduly openamp, tls a vfs.
Canonical vydal Ubuntu Core 24. Představení na YouTube. Nová verze Ubuntu Core vychází z Ubuntu 24.04 LTS a podporována bude 12 let. Ubuntu Core je určeno pro IoT (internet věcí) a vestavěné systémy.
Databáze DuckDB (Wikipedie) dospěla po 6 letech do verze 1.0.0.
Intel na veletrhu Computex 2024 představil (YouTube) mimo jiné procesory Lunar Lake a Xeon 6.
Na blogu Raspberry Pi byl představen Raspberry Pi AI Kit určený vlastníkům Raspberry Pi 5, kteří na něm chtějí experimentovat se světem neuronových sítí, umělé inteligence a strojového učení. Jedná se o spolupráci se společností Hailo. Cena AI Kitu je 70 dolarů.
Byla vydána nová verze 14.1 svobodného unixového operačního systému FreeBSD. Podrobný přehled novinek v poznámkách k vydání.
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. :)