Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Saran entri mirip revisi #18

Merged
merged 1 commit into from
May 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ roh Kudus; roh suci
```

Fitur khusus pengguna yang didukung saat ini adalah etimologi, entri terkait
(kata turunan, gabungan kata, peribahasa, dan idiom), dan batas pencarian yang
lebih besar.
(kata turunan, gabungan kata, peribahasa, dan idiom), saran entri terkait
ketika entri tidak ditemukan, dan batas pencarian yang lebih besar.

Untuk mendapatkan representasi `str`-nya tanpa fitur entri terkait, gunakan
`__str__(terkait=False)`.
Expand All @@ -181,6 +181,26 @@ Etimologi: [Arab] (n) (sg) (f/m) رُوْحٌ rūh: tiupan; sesuatu yang membua
3. (n) (ki) semangat; spirit
```

Untuk memanfaatkan fitur saran entri yang mirip apabila entri tidak dapat
ditemukan, gunakan objek `KBBI` yang terdapat pada objek `TidakDitemukan`
melalui atribut `objek`.

```python
>>> from kbbi import TidakDitemukan
>>> try:
... huk = KBBI("huk", auth)
... except TidakDitemukan as e:
... huk = e.objek
...
>>> print(huk)
Berikut beberapa saran entri lain yang mirip.
auk, buk (1), buk (2), cuk, duk, hak (1), hak (2), hak (3), hak (4), huh, hun, hus, Hut, kuk (1), kuk (2), luk, muk, suk, tuk (1), yuk (1), yuk (2), DUK, HUT, KUK, UK, hub (2), Hud, tuk (2), guk
>>> print(huk.serialisasi())
{'pranala': 'https://kbbi.kemdikbud.go.id/entri/huk', 'entri': [], 'saran_entri': ['auk', 'buk (1)', 'buk (2)', 'cuk', 'duk', 'hak (1)', 'hak (2)', 'hak (3)', 'hak (4)', 'huh', 'hun', 'hus', 'Hut', 'kuk (1)', 'kuk (2)', 'luk', 'muk', 'suk', 'tuk (1)', 'yuk (1)', 'yuk (2)', 'DUK', 'HUT', 'KUK', 'UK', 'hub (2)', 'Hud', 'tuk (2)', 'guk']}
>>> print(huk.saran_entri)
['auk', 'buk (1)', 'buk (2)', 'cuk', 'duk', 'hak (1)', 'hak (2)', 'hak (3)', 'hak (4)', 'huh', 'hun', 'hus', 'Hut', 'kuk (1)', 'kuk (2)', 'luk', 'muk', 'suk', 'tuk (1)', 'yuk (1)', 'yuk (2)', 'DUK', 'HUT', 'KUK', 'UK', 'hub (2)', 'Hud', 'tuk (2)', 'guk']
```

Untuk menonaktifkan fitur khusus pengguna (selain batas pencarian yang lebih
besar), tambahkan argumen `fitur_pengguna=False` pada pemanggilan `__str__`
atau `serialisasi`.
Expand Down
34 changes: 30 additions & 4 deletions src/kbbi/kbbi.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ def __init__(self, kueri, auth=None):
:type auth: AutentikasiKBBI
"""
self.nama = kueri
self.entri = []
self.saran_entri = []
self._init_lokasi()
self._init_sesi(auth)
laman = self.sesi.get(f"{self.host}/{self.lokasi}")
Expand Down Expand Up @@ -74,12 +76,20 @@ def _cek_galat(self, laman):
if "Beranda/BatasSehari" in laman.url:
raise BatasSehari()
if "Entri tidak ditemukan." in laman.text:
raise TidakDitemukan(self.nama)
self._init_saran(laman)
raise TidakDitemukan(self.nama, objek=self)

def _init_saran(self, laman):
if "Berikut beberapa saran entri lain yang mirip." not in laman.text:
return
sup = BeautifulSoup(laman.text, "html.parser")
self.saran_entri = [
saran.text.strip() for saran in sup.find_all(class_="col-md-3")
]

def _init_entri(self, laman):
sup = BeautifulSoup(laman.text, "html.parser")
estr = ""
self.entri = []
label = sup.find("hr").next_sibling
while not (label.name == "hr" and label.get("style") is None):
if label.name == "h2":
Expand All @@ -99,14 +109,22 @@ def serialisasi(self, fitur_pengguna=True):
:returns: Dictionary hasil serialisasi
:rtype: dict
"""
return {
kbbi = {
"pranala": f"{self.host}/{self.lokasi}",
"entri": [
entri.serialisasi(fitur_pengguna) for entri in self.entri
],
}
if self.terautentikasi and fitur_pengguna and not self.entri:
kbbi["saran_entri"] = self.saran_entri
return kbbi

def __str__(self, contoh=True, terkait=True, fitur_pengguna=True):
if self.terautentikasi and fitur_pengguna and self.saran_entri:
return (
"Berikut beberapa saran entri lain yang mirip.\n"
f"{', '.join(self.saran_entri)}"
)
return "\n\n".join(
entri.__str__(contoh, terkait, fitur_pengguna)
for entri in self.entri
Expand Down Expand Up @@ -558,8 +576,9 @@ class Galat(Exception):
class TidakDitemukan(Galat):
"""Galat ketika laman tidak ditemukan dalam KBBI."""

def __init__(self, kueri):
def __init__(self, kueri, objek=None):
super().__init__(f"{kueri} tidak ditemukan dalam KBBI.")
self.objek = objek


class TerjadiKesalahan(Galat):
Expand Down Expand Up @@ -787,6 +806,13 @@ def main(argv=None):
return 1
try:
laman = KBBI(args.laman, auth)
except TidakDitemukan as e:
laman = e.objek
if not args.json:
print(e)
if (laman.saran_entri and args.pengguna) or args.json:
print(_keluaran(laman, args))
return 1
except Galat as e:
print(e)
return 1
Expand Down
23 changes: 18 additions & 5 deletions tests/_mock.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,31 @@
from kbbi import KBBI, AutentikasiKBBI, GagalAutentikasi
from kbbi import KBBI, AutentikasiKBBI, GagalAutentikasi, TidakDitemukan


class MockKBBI(KBBI):
host = "http://localhost:8000"
_host = KBBI.host
lokasi = None

def __init__(self, kueri, auth=None, lokasi=None):
self._auth = auth
self.lokasi = self.lokasi or lokasi
self._lokasi = lokasi
self.lokasi = lokasi
super().__init__(kueri, auth)

def _cek_autentikasi(self, laman):
super()._cek_autentikasi(laman)
self._kembalikan_host_lokasi()

def _kembalikan_host_lokasi(self):
self.host = self._host
if lokasi is None:
self.lokasi = self._lokasi
self.lokasi = self._lokasi

@classmethod
def _init_aman(cls, kueri, auth=None, lokasi=None):
try:
return cls(kueri, auth, lokasi)
except TidakDitemukan as e:
e.objek._kembalikan_host_lokasi()
return e.objek

def _init_lokasi(self):
if self.lokasi is not None:
Expand Down
11 changes: 6 additions & 5 deletions tests/buat_kasus.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
"sage", # terdapat info (bahasa latin)
"semakin", # terdapat entri tanpa makna dan entri lain berupa rujukan
"tampak", # terdapat rujukan dengan nomor
"huk", # saran entri lain yang mirip apabila entri tidak dapat ditemukan
"idn45", # tidak ditemukan dan tidak ada saran entri lain yang mirip
]


Expand Down Expand Up @@ -124,15 +126,14 @@ def buat_semua_objek(daftar):
auth = MockAutentikasiKBBI("foo", "bar")
semua = {"auth": [], "nonauth": []}
for laman in daftar:
semua["auth"].append(MockKBBI(laman, auth))
semua["nonauth"].append(MockKBBI(laman))
semua["auth"].append(MockKBBI._init_aman(laman, auth))
semua["nonauth"].append(MockKBBI._init_aman(laman))
return semua


def buat_semua_kasus(semua, jenis):
for laman, objek in semua.items():
for buat in jenis:
buat(semua)
for buat in jenis:
buat(semua)


def main(daftar=None):
Expand Down
6 changes: 4 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,16 @@ def ambil_atau_simpan(dct, key, func):
@pytest.fixture
def aktual_objek(request, laman):
kueri = request.param
return ambil_atau_simpan(laman, kueri, lambda a: MockKBBI(a))
return ambil_atau_simpan(laman, kueri, lambda a: MockKBBI._init_aman(a))


@pytest.fixture
def aktual_objek_terautentikasi(request, autentikasi, laman_terautentikasi):
kueri = request.param
return ambil_atau_simpan(
laman_terautentikasi, kueri, lambda a: MockKBBI(a, autentikasi)
laman_terautentikasi,
kueri,
lambda a: MockKBBI._init_aman(a, autentikasi),
)


Expand Down
Loading