2 puan yazan GN⁺ 2024-07-26 | 1 yorum | WhatsApp'ta paylaş
  • WAT, Python çalışma zamanında bilinmeyen nesnelerin ne olduğunu hızlıca anlamak için kullanılan bir inspector'dır; type, value, attribute, method, parent type, signature, documentation ve source code'u tek seferde gösterebilir
  • Temel kullanım wat / object şeklindedir ve wat(object) ile aynı şekilde çalışır; ayrıca wat.short / 'foo', 'foo' | wat.short, wat('foo', short=True) gibi çeşitli sözdizimlerini destekler
  • .short, .dunder, .long, .code, .caller, .public, .all, .ret, .str gibi modifier'lar zincirlenerek çıktı kapsamı, dönüş biçimi, renkli çıktı ve çağrı konumu ayarlanabilir
  • Kurulum pip install wat ardından import wat ile yapılabilir; hızlı debug için aynı Python oturumunda kurulum yapmadan kullanılabilen Insta-Load snippet'i de sunulur
  • Django User, re.match, pathlib, colorsys.hsv_to_rgb, typing.List[str], str | None gibi örnekler, WAT'in debug, REPL keşfi ve Python iç yapısını öğrenme için kullanılabileceğini gösterir

WAT ne yapar

  • WAT, Python nesnelerini çalışma zamanında keşfetmek ve incelemek için kullanılan bir araçtır
  • Bilinmeyen bir nesnenin ne olduğunu anlamak zor olduğunda, Python konsolunda wat inspector'ı ile nesnenin yapısı araştırılabilir
  • Herhangi bir object için wat / object çalıştırıldığında şu bilgiler görülebilir
    • nesnenin type
    • biçimlendirilmiş değeri
    • değişkenleri ve method'ları
    • parent type'ları
    • signature
    • documentation
    • source code
  • Aynı derin inceleme wat(object) sözdizimiyle de kullanılabilir
  • Wat, İngilizce what sözcüğünün bir varyasyonu olarak, kafa karışıklığı veya hoşnutsuzluk ifade etmek için kullanılan bir söz olarak tanıtılır

Temel kullanım ve sözdizimi

  • Hızlı yazım için bölme operatörü kullanılır
    • wat / foo, wat(foo) ile aynıdır
  • Aynı inceleme için birden fazla sözdizimi kullanılabilir
    • wat.short / 'foo': hızlı yazım için sözdizimi
    • wat.short('foo')
    • wat('foo', short=True): doğal Python sözdizimi
    • 'foo' | wat.short: Unix pipe tarzı sözdizimi
  • wat.modifier / foo biçimiyle inceleme davranışı ayarlanabilir
  • Modifier'lar zincirlenebilir; örnek olarak wat.short.str.gray / 'foo' verilir
  • Python'da nesneler yalnızca veri yapılarından ibaret değildir; function, class, module ve built-in type'ları da içerdiğinden wat, her türlü nesneyi keşfedebilir
  • Interpreter'da wat yazıldığında, wat nesnesinin kendisiyle ilgili yardım görülebilir

Modifier'larla inceleme kapsamını ayarlama

  • .short veya .s, nesnenin içindeki değişken ve method gibi attribute'ları gizler; yalnızca value, type, parent type, signature ve documentation çıktısını verir
  • .dunder, __ ile başlayan dunder attribute'ları gösterir
  • .long, kısaltılmamış value ve docstring'i gösterir
  • .code, function, method ve class'ların source code'unu gösterir
  • .nodocs, function ve class documentation'ını gizler
  • .caller, incelemenin nasıl ve nereden çağrıldığını gösterir; REPL dışında, dosya içinde çalışır
  • .public, private attribute'ları gizler ve yalnızca public attribute'ları gösterir
  • .all, mümkün olan tüm bilgileri içerir
  • .ret, incelemeden sonra nesneyi tekrar döndürür
  • .str, çıktı yazdırmak yerine sonuç string'ini döndürür
  • .gray, konsoldaki renkli çıktıyı devre dışı bırakır
  • .color, konsolda renkli çıktıyı zorunlu kılar
  • wat.locals local değişkenleri, wat.globals ise global değişkenleri inceler

Kurulum ve Insta-Load

  • pip ile kurulum akışı şöyledir
    • pip install wat
    • Python içinde import wat
  • wat paketinin harici bağımlılığı yoktur
  • Hızlı debug için, aynı Python oturumunda kurulum yapmadan kullanılabilen Insta-Load yöntemi sunulur
  • Insta-Load, base64 ve zlib import edildikten sonra sıkıştırılmış ve encode edilmiş kod string'ini geri açıp exec(..., globals()) ile çalıştıran bir Python snippet'inin interpreter'a yapıştırılması şeklinde çalışır
  • Insta-Load snippet'i çalıştırıldıktan sonra wat object'i kullanılabilir
  • Snippet çalıştırılmadan önce içeriğinin doğrulanması önerilir
    • print(zlib.decompress(base64.b64decode(code)).decode()) ile çıkarılan kod içeriği önceden görülebilir
    • inspection.py içeriğini interpreter'a yapıştırmak da aynı etkiyi verir
    • paketi pip ile kurup kodu inceleme yöntemi de önerilir
  • WAT, tek bir Unicode glyph üzerinden yüklenebilir
  • Unicode string tabanlı loader, uzun emoji ve birleşik karakter string'lerini ord(c) & 255 ile byte dizisine çevirip zlib.decompress(...) sonrasında exec(...) ile çalıştırır

Nesne type'ını ve kullanımını anlama

  • Dinamik tipli bir dil olan Python'da nesne type'ını anlamak bazen zor olabilir; WAT Inspector, type adını ve bu type'ın geldiği module'ü gösterir
  • Type kontrolü örnekleri, value, type ve length bilgisini birlikte gösterir
    • wat.short / (1,), (1,) value'sunu, tuple type'ını ve 1 length'ini çıktılar
    • wat.short / {None}, {None} value'sunu, set type'ını ve 1 length'ini çıktılar
  • Django User nesnesi örneğinde wat.short / user, str: admin, repr: <User: admin>, django.contrib.auth.models.User type'ı ve parent type listesini çıktılar
  • Gerçek type görüldükten sonra, ilerideki karışıklığı azaltmak için koda type annotation eklenebilir
  • Bilinmeyen bir nesnenin nasıl kullanılacağını anlamak için method listesi, signature ve docstring çıktılanabilir
    • örnek olarak wat / ['foo'] verilir
    • docstring'in tamamını görmek için wat.long kullanılır
  • Bir function'ın kullanımını anlamak için function'ın docstring'i ve signature'ı görülebilir
    • örnek olarak wat / str.split verilir

Attribute, module ve source code keşfi

  • İncelenen nesnenin içini görmek için attribute'lar ve her attribute'un type'ı listelenebilir
    • örnek olarak wat / re.match('(\\d)_(.*)', '1_title') verilir
  • Module keşfi için de kullanılabilir; seçilen module'ün function, class ve alt module'leri listelenebilir
    • import pathlib ardından wat / pathlib çalıştırılan bir örnek bulunur
    • sonrasında wat / pathlib.fnmatch gibi daha derine inilebilir
  • WAT Inspector, varsayılan olarak __ ile başlayan attribute'ları gizler
    • wat.dunder / {} ile dunder attribute'ları görülebilir
  • Bir function'ın gerçekte nasıl çalıştığını görmek için source code görüntülenebilir
    • import colorsys ardından wat.code / colorsys.hsv_to_rgb çalıştırılan bir örnek bulunur
  • İç içe dict ve list yapıları, girintili ve okunabilir bir biçimde formatlanır

Debug oturumu ve değişken inceleme

  • Python'un breakpoint() özelliğiyle etkileşimli debugger çalıştırıldıktan sonra, nesneler o anda incelenebilir
  • Pdb örneğinde import wat veya Insta-Load snippet'ini yapıştırdıktan sonra wat / foo ile local değişken incelenir ve c ile yürütmeye devam edilir
  • Local ve global değişkenler sırasıyla wat.locals ve wat.globals ile görülebilir
  • wat() parametresiz çağrıldığında, çağıranın stack'indeki local değişkenleri Local variables başlığı altında yazdırır

Python iç yapısını öğrenme örnekleri

  • Python'un iç çalışma biçimini anlamaya yönelik öğrenme örnekleri de yer alır
  • reversed([]) == reversed([]) ifadesi False döndürür; wat.s / reversed([]) ise value'nun list_reverseiterator nesnesi olduğunu ve type'ının list_reverseiterator olduğunu gösterir
  • wat / type('ObjectCreator', (), {}), dinamik olarak oluşturulmuş class'ın value'sunu, type type'ını ve signature: class ObjectCreator() bilgisini gösterir
  • wat / type, type nesnesinin kendi value'sunu, type type'ını, class type(…) signature'ını, type(object) -> the object's type, type(name, bases, dict, **kwds) -> a new type documentation'ını ve mro gibi public attribute'larını gösterir
  • wat.s / List[str], typing.List[str] value'sunu, typing._GenericAlias type'ını, typing._BaseGenericAlias, typing._Final parent type'larını ve def List(*args, **kwargs) signature'ını gösterir
  • wat(str | None), str | None value'sunu ve types.UnionType type'ını gösterir
  • Python built-in nesnelerini keşfetme örnekleri olarak wat / __builtins__, wat / ... verilir
  • WAT'in kendisi de incelenebilir
    • örnek olarak wat.dunder / wat, wat.code / wat.__truediv__ verilir

İç çalışma özeti

  • inspect_format(obj, *, short=False, dunder=False, nodocs=False, long=False, code=False, caller=False, public=False, all=False), nesne inceleme sonucunu bir string olarak oluşturur
    • all=True ise dunder, long, code, caller birlikte etkinleştirilir
    • public=True ise private çıktı devre dışı bırakılır
    • sys.stdout.isatty() true ise terminal genişliği alınır ve çıktının üstüne ve altına ayraçları eklenir
  • İnceleme çıktısı; nesne value'su, string gösterimi, type, parent type, length, signature, documentation, source code ve attribute bölümleri sırasıyla oluşturulur
  • Attribute incelemesi dir(obj) üzerinde ada göre sıralı dolaşır
    • dunder attribute'lar, dunder ayarı kapalıysa hariç tutulur
    • _ ile başlayan private attribute'lar, private ayarı kapalıysa hariç tutulur
    • getattr(obj, key) sırasında BaseException oluşursa, exception nesnesi value olarak kullanılır
  • Callable nesnelerde signature, inspect.signature(obj) temel alınarak formatlanır
    • başarısız olursa (...) biçiminde yedek bir signature döndürülür
    • class'lara class , coroutine function'lara async def , function, method, built-in veya __name__ taşıyan nesnelere def öneki eklenir
  • code=True olduğunda ve nesne bir class ya da callable ise, inspect.getsource(obj) ile source code çıktılanır
    • OSError, TypeError, IndentationError oluşursa başarısızlık mesajı döndürülür
  • dict ve list formatter'ları, girinti derinliği 30'u aşarsa ERROR: too deeply nested döndürür

Renkli çıktı ve tema

  • Ortam değişkenleriyle renkli çıktı kontrol edilebilir
    • WAT_COLOR="false", konsoldaki renkli çıktıyı devre dışı bırakır
    • WAT_COLOR="true", non-tty ortamlarda bile renkli çıktıyı zorunlu kılar
  • WAT_COLORS ortam değişkeniyle renk teması özelleştirilebilir
  • Varsayılan tema, BAR=0;34,TRAIT=1;34,HEAD=1;37,STR=0;32,NUMBER=0;31,NONE=0;35,TRUE=1;32,FALSE=1;31,DOCS=2;37,KEYWORD=0;34,CALLABLE=1;32,VARIABLE=1;33,CODE=0;33 biçiminde ANSI renk kodu eşlemesidir
  • _strip_color(text), ANSI escape sequence'leri regex ile temizler

İlham

1 yorum

 
GN⁺ 2024-07-26
Hacker News yorumları
  • Vay canına, gerçekten harika. Eskiden benzer bir amaç için python-ls[0] kullanıyordum ama hatırlamadığım bir nedenle bir şeyler bozuldu ve artık bakımı da yapılmıyor
    Bunu büyük ölçüde snoop[1] ve pdbpp'den oluşan hata ayıklama araç kutuma eklemeyi düşünüyorum. wat'tan tek isteğim, Jupyter'de nesne keşfini kolaylaştıracak bir ipy widget olurdu
    base64 exec hack'i de hoşuma gitti. Python'u uzun zamandır kullanıyorum ama bunu şimdiye kadar ne düşünmüştüm ne de görmüştüm; ileride birkaç amaç için kesinlikle deneyeceğim
    [0] https://github.com/gabrielcnr/python-ls
    [1] https://pypi.org/project/snoop/

  • Eğlenceli görünüyor. Python'da her zaman dir kullanıyorum ve belgelerin zayıf olduğu durumlarda bazen resmî dokümanlardan bile daha faydalı olabiliyor
    Etkileşimli kabuk Python'un gerçek güçlü yanlarından biri ama etrafında bunun gibi daha fazla yeni araç ya da yenilik olmaması şaşırtıcı

    • Bir de help() fonksiyonu var. Gerçekten faydalı
  • Eski icecream'in daha gösterişli bir sürümü gibi görünüyor
    https://github.com/gruns/icecream
    Bilmiyorsanız aşağıdaki diğer diller için uygulama listesine de bakın
    https://github.com/gruns/icecream#icecream-in-other-language...

  • Bu tür araçlar faydalı oluyor
    20 yıl önce Zope için bir nesne introspector'ü yapmıştım
    Bugünlerde her gün devtools kullanıyorum, icecream ve q'yu da ara sıra kullanıyorum. wat'ı da bir deneyeceğim

  • from wat import wat
    Projenin karakteri bu kadar havalıyken, aynı kullanım sözdizimiyle düz import wat sunmaması şaşırtıcı. Böylece meraklı kullanıcıların wat/wat deneyip numarayı keşfetmesi de sağlanabilirdi

    • import wat güzel olurdu ama Python'da modülleri çağrılabilir hâle getirememe kısıtı var. Bu yüzden daha uzun olan from wat import wat yoluna gidilmiş
      Emin değilim ama import wat; wat.wat / object daha kullanışlı da olabilir
  • Çok faydalı görünüyor ama okunabilirlik adına tamamen ilgisiz operatörlerin, burada / operatörünün, aşırı yüklenmesi yönündeki son eğilimden rahatsız olan tek kişi ben miyim diye merak ediyorum

    • Bu durumda / aşırı yüklemesinin tuhaf bir seçim olduğuna katılıyorum. Yine de is'in aşırı yüklenememesi üzücü. Gerçekte wat(foo) tek başına da yeterli olurdu gibi geliyor
  • Uğraştırıcı import'tan kaçınmak için $PYTHONSTARTUP dosyasına şunları da ekleyebilirsiniz
    try:
    from wat import wat
    except ImportError:
    pass

    • Hatta oldukça hoş bir base64 satır içi import edici bile ekleyebilirsiniz
      Sonunda onun çıktısını yazdırıp, her zaman kullanılabilsin diye PYTHONPATH'in işaret ettiği dizine koydum
      Sürekli kullanır mıyım, göreceğiz
  • Vay, Python öğrenirken böyle bir araç olsaydı oyunun kurallarını değiştirirdi diye düşünüyorum. Bir dili öğrenirken içeride neler olduğunu görmek temel yollardan biri ama Python'un varsayılan hata ayıklaması en iyi ihtimalle hayal kırıklığı yaratıyor
    Bunun yerine pry kurup koyu bir Ruby hayranı olmuştum ama bu araç Python'u yeniden denememe neden olabilir

  • Yazar, işlevselliği sağlamak için arka planda standart kütüphanedeki Python inspect modülünü kullanıyor. Elbette bunun üzerine çok fazla ek değer katmış
    wat modülündeki inspection.py dosyasına bakabilirsiniz
    2. satırda şunu görüyorsunuz:
    import inspect as std_inspect

  • “Bir şeyi hızlıca debug etmek istiyorsanız, aynı oturumda hiçbir şey kurmadan bu inspector'ü kullanabilirsiniz”
    “Bu snippet'i Python yorumlayıcısına yapıştırıp anında yükleyin”
    Proje README'sine tüm projenin bir kopyasını base64 ile kodlanmış sıkıştırılmış veri olarak koyma fikri oldukça dahiyane
    Özellikle gerçekten ihtiyaç duyulacak ortamlara önceden koymayı düşünmemiş olabileceğiniz bu tür projeler için çok uygun