Portál AbcLinuxu, 31. října 2024 23:49
Tiskni Sdílej:
Původní problém byl, že ta aplikace sama neuměla porovnat dva názvy souborů.Nemyslim. IMHO puvodni problem byl v tom, ze uzivatel zadal do programu jmeno souboru, program to jmeno predal operacnimu systemu a OS ten soubor nenasel, protoze byl na FS v jine variante (nenormalizovan, s jinou normalizaci). Tedy porovnavani neprovadel program, ale OS, a ten se (v pripade Linuxu) o kodovani nestara, pro nej to jsou posloupnosti bytu.
což je ještě okořeněné tím, že že by teoreticky mohlo být na disku více různých souborů vedoucích na stejný normalizovaný název. Což by hrozilo spíš bezpečnostním průšvihem, než že by takové soubory někdo normálně vyrobil.To se klidne muze stat, i kdyz to . Podobne jako pripady, kdy jsou na disku soubory se jmeny, ktere nejsou validni UTF-8 sekvence. Nebo treba jmena souboru obsahujici ridici znaky (< 32). Rozumny software by se s takovymi pripady mel rozumne vyrovnat.
A jinak u názvů souborů snad nemá smysl dělat jinou normalizaci než Normalization Form Compatibility Composition, ne?V Linuxu asi jo, nicmene treba OS X udajne pouziva NFD.
OS X udajne pouziva NFDTo by mohlo vysvětlovat, že Safari z OS X posílá v HTTP požadavcích dekomponované znaky a Apache si to neumí normalizovat, takže to pak nefunguje.
Proč by prohlížeč prováděl normalizaci? Od uživatele dostal posloupnost znaků v UnicodeUzivatel nezadal posloupnost znaku v Unicode, uzivatel stiskl fyzicke klavesy na klavesnici. Na jakou posloupnost znaku v Unicode se to prelozilo, to uz je zalezitost OS+toolkitu+programu.
No, podival jsem se na rozdil mezi NFC a NFKC a IMHO pro ucely ukladani normalizovanych jmen souboru je NFKC nepouzitelne, tam je treba pouzit NFC (nebo NFD, pokud by cloveka nezajimala kompatibilita se stavajicim software).Původní problém byl, že ta aplikace sama neuměla porovnat dva názvy souborů.A jinak u názvů souborů snad nemá smysl dělat jinou normalizaci než Normalization Form Compatibility Composition, ne?V Linuxu asi jo, nicmene treba OS X udajne pouziva NFD.
NFD má lepší binární řazení (či řazení v ASCII), protože znaky s diakritikou jsou za stejnými znaky bez diakritikyTo me prijde jako zanedbatelna vyhoda, nebot vzhledem k odlisnemu poctu code pointu se takove porovnani stejne hned po prvnim znaku rozsype.
Kompatibilita je dobrá pro porovnávání, ale ne pro ukládání, protože může měnit význam v určitých kontextech.Jo, to je pravda. V kontextu, ktery jsem resil, nema NFKD / NFKC smysl.
To me prijde jako zanedbatelna vyhoda, nebot vzhledem k odlisnemu poctu code pointu se takove porovnani stejne hned po prvnim znaku rozsype.Proč by se mělo rozsypat? Znaky se při řazení porovnávají od začátku, a pokud se nějaké znaky nerovnají, další se už neporovnávají, bez ohledu na to, kolik jich následuje. Č se rozloží na Cˇ (kombinující znaky jsou za znaky, se kterými se kombinují, právě kvůli řazení), což se umístí za CZ (C == C, Z < ˇ), ale před DA (D > C, dál už se neporovnává). V MacOS X to funguje poměrně dobře, třeba v Linuxu s českou lokalizací je ѓ až za я (protože česká lokalizace nemá pravidlo pro ѓ a code point je vyšší než я), ale v MacOS X je za poslední položkou začínající г a před д, což je velmi dobře umístěné.
Přehlédl jste, že tak se to seřadí.
ER, ÉF, ĚC se normalizují na ER, E´F, EˇC.
Nejprve se řadí prvním znakem. Všechny jsou stejné, pokračuje se dále.
Poté se řadí druhým znakem. U E´F se (dle pravidla) čárka přeskočí a porovnává se místo ní další znak:
ER × E´F. R > F. E´F bude před ER.
ER × EˇC. ˇ > R, ER bude před EˇC.
Výsledek: ÉF, ER, ĚC.
Výsledek: ÉF, ER, ĚC.Což není správně podle českého abecedního řazení, mělo by to být ĚC, ÉF, ER – v prvním průchodu se diakritiky u E ignorují, ale už po prvním průchodu jsou tato slova seřazená, není tam žádná nejasnost, která by vyžadovala druhý průchod.
Znaky se při řazení porovnávají od začátku, a pokud se nějaké znaky nerovnají, další se už neporovnávají, bez ohledu na to, kolik jich následuje.Jo, to je pravda (sice by se to rozsypalo, ale v tu chvili uz je rozhodnuto). Tedy az do chvile, kdy to nekdo bude chtit kombinovat se znakama z dalsich bloku za compose symboly (napr. s rozsirenou interpunkci ci matematickymi symboly), pak NFD povede k horsimu binarnimu usporadani nez NFC (Č bude za CZ, ale pred C‡).
Kompatibilita je dobrá pro porovnávání, ale ne pro ukládání, protože může měnit význam v určitých kontextech.Psal jsem právě o porovnávání. Ukládat by se podle mne mělo přesně to, co dostanu na vstupu, tedy nenormalizovaný název. To má samozřejmě tu nevýhodu, že se to pak při zpracování obvykle musí normalizovat. Ale myslím, že o normalizaci se nedá rozhodnout obecně, že si o konkrétním použití musí rozhodnout aplikace.
To ale není typické použití. Typicky program vypíše seznam souborů a uživatel si ze seznamu nějaký vybere.Jak kdy a jak kde. Rekl bych, ze na svem systemu mam nainstalovano radove vic tech programu, kde se jmeno zadava, nez tech, kde se soubor vybira.
A i když uživatel zadává jméno souboru přímo, zadává Unicode znakyJak jsem psal vyse, uzivatel macka klavesy a vidi jako odezvu grafemy. A typicky netusi, jake unicodove sekvence se vygeneruji.
takže pokud by měl uživatel soubor s názvem poskládaným ze znaku a znaménka, nebo soubor obsahující v názvu slitek, holt by to tak musel také napsatCoz je koneckoncu to, na co si stezoval OP (Tomáš). IMHO v Unicode je to mysleno opacne - rozdily mezi kodovanim jsou imaterialni, pokud jsou vstupni unicodove sekvence kanonicky ekvivalentni, tak reprezentuji stejny retezec abstraktnich znaku a prislusna akce by mela dopadnout stejne.
Rekl bych, ze na svem systemu mam nainstalovano radove vic tech programu, kde se jmeno zadava, nez tech, kde se soubor vybira.To ty názvy souborů opravdu píšete od začátku do konce? Nepoužíváte doplňování shellu?
Jak jsem psal vyse, uzivatel macka klavesy a vidi jako odezvu grafemy. A typicky netusi, jake unicodove sekvence se vygeneruji.Příčetný ovladač klávesnice generuje vždycky složený znak – skládání po částech ze základního znaku a znaménka je pokud vím vyhrazeno pro speciální případy. Setkal jsem se s jediným případem, kdy klávesnice generuje sekvenci znak + znaménko, a to je při použití mrtvých kláves v konzoli Archu. A je to tam špatně, protože to pak font mapper nedokáže správně zobrazit.
IMHO v Unicode je to mysleno opacne - rozdily mezi kodovanim jsou imaterialni, pokud jsou vstupni unicodove sekvence kanonicky ekvivalentni, tak reprezentuji stejny retezec abstraktnich znaku a prislusna akce by mela dopadnout stejne.Kdyby to tak bylo, není přece potřeba mít v Unicode pro jednu kanonicky ekvivalentní sekvenci několik různých možností kódování.
To ty názvy souborů opravdu píšete od začátku do konce? Nepoužíváte doplňování shellu?Jméno souboru může znakem s diakritikou i začínat.
Příčetný ovladač klávesnice generuje vždycky složený znak – skládání po částech ze základního znaku a znaménka je pokud vím vyhrazeno pro speciální případy. Setkal jsem se s jediným případem, kdy klávesnice generuje sekvenci znak + znaménko, a to je při použití mrtvých kláves v konzoli Archu. A je to tam špatně, protože to pak font mapper nedokáže správně zobrazit.Ta chyba generuje znak a nekombinující diakritiku (dělal to občas třeba Skype, resp. vstupní systém ibus). Znak + kombinující diakritika je z definice kanonické kompatibility vykreslen totožně jako kombinovaný znak (a projde třeba i kontrolou pravopisu, pokud správně implementuje Unicode) a klávesnice takovou sekvenci klidně může generovat. Tento odstavec jsem napsal bez použití složených znaků a zobrazí se vám totožně, jako by složené znaky obsahoval
Kdyby to tak bylo, není přece potřeba mít v Unicode pro jednu kanonicky ekvivalentní sekvenci několik různých možností kódování.Ten důvod je zpětná kompatibilita s dříve existujícími standardy (hlavně ISO 8859). U kanonické ekvivalence je z definice jedno, kterou formu použijete, všechny mají tentýž význam a vzhled.
Řetězec není pole pole bajtů - Python to dělá zcela správně. Chápu, že špatné návyky z C, ...Abstraktni 'retezec' mozna neni. Nicmene jsme na unixovem systemu, kde API dodrzuje C konvence, tak se s tim musi pocitat. A jmeno souboru je zde C-retezec, tedy zero terminated pole bytu. Pokud nejaky jazyk ma 'skutecne' retezce zalozene na 'skutecnych' znacich, tak pak musi pocitat s tim, ze funkce pro praci se soubory by nemely dostavat 'skutecne' retezce ale jine objekty (C-retezce). Pokud se jazyk snazi tento detail skryt, tak si zadelava na spoustu tezko resitelnych problemu. V Linuxu neni kodovani nastaveno per-filesystem, ale per-user, takze zcela legitimne mohou byt na jednom filesystemu soubory se jmeny v ruznych kodovani (a bez informace o pouzitem kodovani). Rozumne programy by v takove situaci nemely selhat a mely by fungovat tak dobre, jak to jen jde.
V Linuxu neni kodovani nastaveno per-filesystem, ale per-user, takze zcela legitimne mohou byt na jednom filesystemu soubory se jmeny v ruznych kodovani (a bez informace o pouzitem kodovani).Což je jednoznačně chyba, a je dost smutné, že už to dávno nebylo vyřešeno. (Nijak nerozporuju, jak to historicky vzniklo – ale už to mělo být dávno vyřešeno. Ostatně stejně jako to, že u souborů normálně neukládáme ani jejich typ a případně kódování obsahu.) Mnoho souborů je viditelných pro více uživatelů, a dokonce ani kódování uživatele není persistentní, dává smysl, aby jeden uživatel spouštěl programy s různě nastaveným kódováním.
Což je jednoznačně chyba, a je dost smutné, že už to dávno nebylo vyřešeno.Existuje vlastně ještě nějaký důvod, proč používat cokoli jiného než UTF-8?
FAT32 z českých Windows prostě bude mít vždy názvy ve Windows-1250.Naopak. AFAIK, FAT32 pouziva pro long filenames interne UCS-2, pri pristupu z Linuxu se ta jmena prekodovavaji do linuxoveho formatu ve zvolenem kodovani (mount option iocharset).
Řetězec není pole pole bajtů - Python to dělá zcela správně. Chápu, že špatné návyky z C, kde řetězec de facto vůbec neexistuje, a tváří se, že pole integerových čísel je řetězec - to przní.Python to správně nedělá, byla tu o tom už nejedna diskuze. Správně to momentálně dělá třeba nový Perl, v pythonu je to docela zprasenina.
Python to samozřejmě dělá správně a nový Perl to dělá špatně.Doloz dukaz.
Mám načtený standard Unicode zleva doprava a zpět tolikrát, až to hezké není. Programoval jsem kolem Unicode hodně věcí.To je velmi bidna a nedostatecna podpora tvych vyroku.
I když budete tisíckrát tvrdit a řvát, že nový Perl to dělá správně - pouze sázíte na to, že tisíckrát opakovaná lež se stane pravdou podle Goebbelsova hesla. Ale pravda to nikdy nebude.Obsahove irelevantni.
To co dělá Perl žádnou podporu ve standardu Unicode nemá, a to zcela logicky, protože standardizátoři Unicode se nad tím zamýšleli do všech důsledků - ne jako autor Perlu, který rozšlehal Perl na maděru a z původně rozšířeného jazyka udělal jazyk, který prakticky používá už jen pár studentů historie. Teď se snaží na maděru rozšlehat i standard Unicode, ale naštěstí k tomu nemá moc a páky.Osobni, nijak nepodlozeny nazor.
Autor Perlu se řídí stylem, že lepší drzé čelo než poplužní dvůr. Nicméně nedokáže svůj kreativní a hochštaplerský přístup k Unicode - k velkému štěstí celého světa - prosadit ani nabořit.Osobni, utocny, nijak nepodlozeny nazor. V kazdem pripade irelevantni.
Možná ale že autor Perlu příště udělá inovativní přístup třeba k dalším věcem. Zmrvit jde spousta věcí, proč ne jenom Unicode? Stačí se jen vytentovat na zavedené, fungující a promyšlené standardy - a hrát si joudu záměrně standardy porušující, jak se to děje v Perlu.Spekulace a osobni utoky. V kazdem pripade irelevantni.
Python to dělá správně.Nulova argumentace.
protože standardizátoři Unicode se nad tím zamýšleli do všech důsledků[citation needed] :)
bytes
je kdykoliv ho vrazíš do nějaké knihovny (html parser třeba), tak ho většinou bude má snahu převést na string a v tu chvíli se to celé rozpadne.
Ideální by bylo ideální mít nějakou možnost jak říct „mám na čůráku a je mi jedno, že z toho budou paznaky, teď to chci prostě zpracovat“, tak přestaň vyhazovat výjimky kdykoliv kdy nad tím dělám nějakou stringovou operaci. Což bytes
trochu umožňuje, ale nejde to dost do hloubky.
Jak se parsuje HTML bez (alespoň částečné) znalosti kódování?Naprostá většina kódování, kromě na internetu prakticky nepoužívaných výjimek používá fallback na ASCII. HTML je psané v ASCII rozsahu, takže tady není problém. Častější příklad je že je to prostě špatně, nebo jsou tam zmixované různé věci dohromady. Jako příklad jsem uváděl třeba zdejší systém, kde máš HTML v UTF-8 a do toho je nacpaná reklama v nějakém jiném kódování, takže výsledek je nevalidní zprasenina.
Používá se třeba UTF-16, a tipuju, že občas i na internetu.To jsem ještě neměl tu smůlu potkat.
/u/46/necadam1/unix/.local/lib/python3.4/site-packages/numba/dispatcher.py in _compile_for_args(self, *args, **kws) 275 else: 276 real_args.append(self.typeof_pyval(a)) --> 277 return self.compile(tuple(real_args)) 278 279 def inspect_llvm(self, signature=None): /u/46/necadam1/unix/.local/lib/python3.4/site-packages/numba/dispatcher.py in compile(self, sig) 493 494 self._cache_misses[sig] += 1 --> 495 cres = self._compiler.compile(args, return_type) 496 self.add_overload(cres) 497 self._cache.save_overload(sig, cres) /u/46/necadam1/unix/.local/lib/python3.4/site-packages/numba/dispatcher.py in compile(self, args, return_type) 74 impl, 75 args=args, return_type=return_type, ---> 76 flags=flags, locals=self.locals) 77 # Check typing error if object mode is used 78 if cres.typing_error is not None and not flags.enable_pyobject: /u/46/necadam1/unix/.local/lib/python3.4/site-packages/numba/compiler.py in compile_extra(typingctx, targetctx, func, args, return_type, flags, locals, library) 694 pipeline = Pipeline(typingctx, targetctx, library, 695 args, return_type, flags, locals) --> 696 return pipeline.compile_extra(func) 697 698 /u/46/necadam1/unix/.local/lib/python3.4/site-packages/numba/compiler.py in compile_extra(self, func) 367 raise e 368 --> 369 return self.compile_bytecode(bc, func_attr=self.func_attr) 370 371 def compile_bytecode(self, bc, lifted=(), lifted_from=None, /u/46/necadam1/unix/.local/lib/python3.4/site-packages/numba/compiler.py in compile_bytecode(self, bc, lifted, lifted_from, func_attr) 376 self.lifted_from = lifted_from 377 self.func_attr = func_attr --> 378 return self._compile_bytecode() 379 380 def compile_internal(self, bc, func_attr=DEFAULT_FUNCTION_ATTRIBUTES): /u/46/necadam1/unix/.local/lib/python3.4/site-packages/numba/compiler.py in _compile_bytecode(self) 660 661 pm.finalize() --> 662 res = pm.run(self.status) 663 if res is not None: 664 # Early pipeline completion /u/46/necadam1/unix/.local/lib/python3.4/site-packages/numba/compiler.py in run(self, status) 255 # No more fallback pipelines? 256 if is_final_pipeline: --> 257 raise patched_exception 258 # Go to next fallback pipeline 259 else: /u/46/necadam1/unix/.local/lib/python3.4/site-packages/numba/compiler.py in run(self, status) 247 try: 248 event(stage_name) --> 249 stage() 250 except _EarlyPipelineCompletion as e: 251 return e.result /u/46/necadam1/unix/.local/lib/python3.4/site-packages/numba/compiler.py in stage_objectmode_backend(self) 583 """ 584 lowerfn = self.backend_object_mode --> 585 self._backend(lowerfn, objectmode=True) 586 587 # Warn if compiled function in object mode and force_pyobject not set /u/46/necadam1/unix/.local/lib/python3.4/site-packages/numba/compiler.py in _backend(self, lowerfn, objectmode) 560 self.library.enable_object_caching() 561 --> 562 lowered = lowerfn() 563 signature = typing.signature(self.return_type, *self.args) 564 self.cr = compile_result(typing_context=self.typingctx, /u/46/necadam1/unix/.local/lib/python3.4/site-packages/numba/compiler.py in backend_object_mode(self) 534 self.library, 535 self.interp, --> 536 self.flags) 537 538 def backend_nopython_mode(self): /u/46/necadam1/unix/.local/lib/python3.4/site-packages/numba/compiler.py in py_lowering_stage(targetctx, library, interp, flags) 846 fndesc = funcdesc.PythonFunctionDescriptor.from_object_mode_function(interp) 847 lower = objmode.PyLower(targetctx, library, fndesc, interp) --> 848 lower.lower() 849 if not flags.no_cpython_wrapper: 850 lower.create_cpython_wrapper() /u/46/necadam1/unix/.local/lib/python3.4/site-packages/numba/lowering.py in lower(self) 140 141 # Materialize LLVM Module --> 142 self.library.add_ir_module(self.module) 143 144 def extract_function_arguments(self): /u/46/necadam1/unix/.local/lib/python3.4/site-packages/numba/targets/codegen.py in add_ir_module(self, ir_module) 144 self._raise_if_finalized() 145 assert isinstance(ir_module, llvmir.Module) --> 146 ll_module = ll.parse_assembly(str(ir_module)) 147 ll_module.name = ir_module.name 148 ll_module.verify() /u/46/necadam1/unix/.local/lib/python3.4/site-packages/llvmlite/binding/module.py in parse_assembly(llvmir) 14 """ 15 context = ffi.lib.LLVMPY_GetGlobalContext() ---> 16 llvmir = _encode_string(llvmir) 17 strbuf = c_char_p(llvmir) 18 with ffi.OutputString() as errmsg: /u/46/necadam1/unix/.local/lib/python3.4/site-packages/llvmlite/binding/common.py in _encode_string(s) 15 else: 16 def _encode_string(s): ---> 17 encoded = s.encode('latin1') 18 return encoded 19 UnicodeEncodeError: 'latin-1' codec can't encode character '\u03b8' in position 1927: ordinal not in range(256)
!! nepamatuji si, kdy jsem naposledy použil ÚMYSLNĚ caps, akorát si ho vždycky omylem zapnu při netrefení se do TABu (nejpoužívanější klávesa clear lock !! trojtečka … místo § keycode 48 = ellipsis exclam NoSymbol NoSymbol apostrophe ssharp !! § přesuneme o dvě klávesy doleva keycode 46 = l L NoSymbol NoSymbol Lstroke section !! spojovník – na klávese vedle backspace keycode 51 = dead_diaeresis endash NoSymbol NoSymbol backslash bar !! když už je na Q Ω, tak se hodí i μ keycode 24 = q Q NoSymbol NoSymbol Greek_omega Greek_OMEGA keycode 25 = w W NoSymbol NoSymbol Greek_mu Greek_MU !! z capslocku uděláme „typo“ klávesu pro kůůl češtinu! keycode 66 = doublelowquotemark leftdoublequotemark !! keycode 135 = a keycode 135 = Mode_switch keycode 0xb = ecaron Ecaron 2 NoSymbol at dead_caron keycode 0xc = scaron Scaron 3 NoSymbol numbersign dead_circumflex keycode 0xd = ccaron Ccaron 4 NoSymbol dollar dead_breve keycode 0xe = rcaron Rcaron 5 NoSymbol percent dead_abovering keycode 0xf = zcaron Zcaron 6 NoSymbol asciicircum dead_ogonek keycode 0x10 = yacute Yacute 7 NoSymbol ampersand dead_grave keycode 0x11 = aacute Aacute 8 NoSymbol asterisk dead_abovedot keycode 0x12 = iacute Iacute 9 NoSymbol braceleft dead_acute keycode 0x13 = eacute Eacute 0 NoSymbol braceright dead_doubleacute !!keycode 107 = Next !! tohle jsem přemapoval protože notebook má blbě funkční klávesy pro nastavení jasu. Nastavení jasu tady nevidíte, to se dělá jinde. keycode 127 = F12 keycode 96 = Pause !! iirc nějaká věc aby to psalo čísla i s omylem vypnutým numlockem keycode 90 = 0 keycode 87 = 1 keycode 88 = 2 keycode 89 = 3 keycode 83 = 4 keycode 84 = 5 keycode 85 = 6 keycode 79 = 7 keycode 80 = 8 keycode 81 = 9 keycode 173 = Home keycode 171 = End
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.