23 Ocak 2015 Cuma

Python Paketi Hazırlamak

    Pebble Remote projesinin bana katkısı gerçekten çok büyük oldu. Daha buraya yazmadığım bir sürü büyük küçük birbirini gerektiren bi çok işi öğrendim.  Paketlemeyi öğrenme amacım pebble remote'un pip komutuyla kurulabilir hale gelmesini sağlamaktı.

Şimdi örnek olarak aşağıdaki python projesini pip ile kurulabilir hale getireceğiz

pebbleremote
└── pebble
    ├── bluetooth.py
    ├── data
    │   └── logo.png
    ├── __init__.py
    ├── py_script.py
    └── remote.py

setup.py dosyasını yazmalıyız

Öncelikle bu dosyanın yukarıdaki pebble modülü ile aynı seviyede olması gerekiyor.

pebble
├── pebble
│   ├── bluetooth.py
│   ├── data
│   │   └── logo.png
│   ├── __init__.py
│   ├── py_script.py
│   └── remote.py
└── setup.py

setup.py dosyasının içinde bulunması gerekenler:


from setuptools import setup

setup(name='pebble-remote',
      version='1.0',
      description='Libreoffice Impress tool for remoting presentations with Pebble',
      url='http://github.com/Libreoffice/impress_remote/tree/master/pebble',
      author='Gulsah Kose',
      author_email='gulsah.1004@.gmail.com',
      license='MPLv2',
      packages=['pebble'],

      scripts=['pebble/py_script.py'],

      install_requires = ['setuptools'], 
      zip_safe=False)

Bu kadarını yazdığımızda sadece pebble modülünü gereken yere kuracak hale getirmiş oluruz. Ama içinde yukarıda olduğu gibi bir python dosyası olmayan modüle dahil olmayan dosyalar olabilir -data dizini ve altındaki png dosyası gibi-.

Onuda pakete dahil etmek için aşağıdaki yolu izliyoruz:

- Öncelikle MANIFEST.in dosyasının içinde aşağıdaki satırı  yazalım Bunu modül dışında olan dosyaları pakete dahil etmek için kullanıyoruz:

include /pebble/data/logo.png

 pebble
├── MANIFEST.in
├── pebble
│   ├── bluetooth.py
│   ├── data
│   │   └── logo.png
│   ├── __init__.py
│   ├── py_script.py
│   └── remote.py
└── setup.py

 - Bu ekleme için setup.py dosyasının içeriğini de değiştirmemiz gerekecek. Dosyanın son hali aşağıdaki gibi olacak:


from setuptools import setup 

setup(name='pebble-remote',
      version='1.0',
      description='Libreoffice Impress tool for remoting presentations with Pebble',
      url='http://github.com/Libreoffice/impress_remote/tree/master/pebble',
      author='Gulsah Kose',
      author_email='gulsah.1004@.gmail.com',
      license='MPLv2',
      packages=['pebble'],

      scripts=['pebble/py_script.py'],

      package_data={
          'pebble/data': ['logo.png'],
      },

      data_files=[
          ('/opt/pebble/logo/', ['pebble/data/logo.png'])

      ], 

      install_requires = ['setuptools'], 

      zip_safe=False)


Artık projemiz kurulmaya hazır hale gelmiştir. Aşağıdaki komutu kullanarak kurulumunu yapabilirsiniz:

$sudo python setup.py install

Kurulumu bu şekilde yaptığınızda paketi kaldırmak için aşağıdaki komutları kullanabilirsiniz:

$sudo python setup.py install --record file.txt
 
#cat file.txt | xargs rm -rf

 Şimdi bu projeyi python package index (PyPi) 'e yükleyelim:

Önce bu adresten bir hesap oluşturmalısınız. Projenizi buraya yüklemeden önce depoda aynı isimde başka bir proje varmı diye bakmalısınız. Çünkü pypi'de tüm paket isimleri eşsiz olmalıdır.

Sonra aşağısaki komutu çalıştırdığınızda karşınıza size kullanıcı adı parola gibi bilgilerinizi soran kısımlar çıkacak. Bunları doğru bir şekilde tamamladığınızda herşey yolundaysa 200(OK) kodunu göreceksiniz. Bunu gördüğünüzde artık projeniz pip ile kurulabilir hale gelmiş olacak.
 
$sudo python setup.py register sdist upload
 
Artık #pip install pebble-remote yazdığınızda projeniz sorunsuz kuruluyor olmalı.


Paketlemeyi öğrenirken faydalandığım linkler burada. Yukarıdaki setup.py dosyası içindeki alanların ne anlama geldiği ayrıntılı anlatılıyor:

1) http://www.scotttorborg.com/python-packaging/minimal.html#
2) https://pythonhosted.org/setuptools/setuptools.html

Bununla ilgili çok örnek bulmanız mümkün elbet ama pebble remote için yaptığım paketi aşağıdaki linkten inceleyebilirsiniz

3) https://pypi.python.org/pypi/pebble-remote/2.0

15 Ocak 2015 Perşembe

Python'da Kullanıcı Tanımlı Hatalar

    Python projelerinde kullanıcılar hata tanımlayabilir ve aynı sistem tarafından tanımlı hatalar gibi try-except içinde kullanabilir.

    Ben pebble-remote projesini geliştirirken bu hata yakalama kısmında şöyle bir sorunla karşılaşmıştım. Kullanıcı tanımlı hata sınıflarım vardı ve bu sınıfların tanımlandığı dosyanın dışında bir yerde bu tanımlanan hataları yakalamak istiyordum. Hatanın tanımlandığı python dosyasını da import ettiğim halde bu hataları yakalayamıyordum.

   Daha iyi bir yöntemi de olabilir elbet ama benim deneyerek bulduğum çözüm hata sınıfının tam yolunu yazmak oldu.

Kullanmaya çalıştığım python modülünün yapısı aşağıda:

libpebble/pebble
├── __init__.py
├── LightBluePebble.py
├── pebble.py
└── stm32_crc.py

LightBluePebble.py dosyası içinde bir hata aşağıdaki gibi tanımlanmış:


LightBluePebbleError(Exception):
    def __init__(self, id, message):
        self._id = id
        self._message = message
    def __str__(self):
        return "%s ID:(%s) on LightBlue API" % (self._message, self._id)

Bu hatayı yakalamak istediğim dosya içinde  içinde modülü aşağıda şekilde import ettim:


import pebble as libpebble

Bu haliyle aşağıdaki kod hatalıydı:


try:
    ...
except LightBluePebbleError as e
    ...

Doğrusu:


LightBluePebbleError = libpebble.LightBluePebble.LightBluePebbleError

try:
    ...
except LightBluePebbleError as e
    ...

Python Projelerine Mimetype Desteği Eklemek

    Python projeniz eğer sadece konsol aracıysa ve bunu sağ tıkla şununla aç şeklinde çalıştırılabilecek hale getirmek istiyorsanız projenize mimetype desteği eklemeniz gerekir.

    Benim buna ihtiyaç duymam, gururla daha çok yerde anlatacağım bir olayın arkasından oldu. Bu sene bitirme projemin bir parçası olarak Pebble ile LibreOffice Impress uzaktan kumandasını yazdım. Ve yazdığım araç bir hafta önce LibreOffice deposuna kabul edildi. Ve daha güzeli LibreOffice deposunun tümüne yazma hakkım olması ve listedekilerin "LibreOffice geliştirici ekibine hoşgeldin" demeleriydi. O anki heyecanımla Çanakkaleyi koşarak turlayabilirdim :) Bu süreçteki tüm desteği için Necdet hocama ne kadar teşekkür etsem az. pebble-remote kabul edildikten sonra bu projenin kullanımını kurulumunu basitleştirmeye çalıştım. Mimetype desteğini eklediktan sonra pebble-remote artık sadece bir konsol aracı olmaktan çıktı ve kullanımı çok çok kolaylaştı.

Mimetype desteği eklenmesi şu adımlarla gerçekleştirdim:


* Menüde görünecek logoyu belirledim ve bu logoyu /usr/share/pixmaps/ dizini altına pebble-remote.png ismiyle kopyaladım.












* Menüde görünebilir hale gelmesi için aşağıdaki dosyayı  /usr/share/menu/ altına pebble-remote adıyla kopyaladım. 

---
?package(pebble-remote):needs="X11" section="Applications/Office"\
  title="Pebble Remote" command="/usr/bin/pebble-remote"\
  hints="Presentation"\
  kderemove="y"\
  icon="/usr/share/icons/hicolor/32x32/apps/libreoffice-impress.xpm"
---

* Aşağıdaki dosyayı  /usr/share/applications/ dizini altına pebble-remote.desktop ismiyle kaydettim:

---
[Desktop Entry]
Version=1.0
Terminal=false
Icon=/usr/share/pixmaps/pebble-remote.png
Type=Application
Categories=Office;Presentation;X-Red-Hat-Base;X-MandrivaLinux-Office-Presentations;
Exec=pebble-remote %U
MimeType=application/vnd.oasis.opendocument.presentation;application/vnd.oasis.opendocument.presentation-template;application/vnd.sun.xml.impress;application/vnd.sun.xml.impress.template;application/mspowerpoint;application/vnd.ms-powerpoint;application/vnd.openxmlformats-officedocument.presentationml.presentation;application/vnd.ms-powerpoint.presentation.macroenabled.12;application/vnd.openxmlformats-officedocument.presentationml.template;application/vnd.ms-powerpoint.template.macroenabled.12;application/vnd.openxmlformats-officedocument.presentationml.slide;application/vnd.openxmlformats-officedocument.presentationml.slideshow;application/vnd.ms-powerpoint.slideshow.macroEnabled.12;application/vnd.oasis.opendocument.presentation-flat-xml;application/x-iwork-keynote-sffkey;
Name=Pebble Remote
GenericName=Presentation
Comment=Pebble remote control for LibreOffice Impress.
StartupNotify=true
Keywords=Slideshow;Slides;OpenDocument Presentation;Microsoft PowerPoint;Microsoft Works;OpenOffice Impress;odp;ppt;pptx;
InitialPreference=5
StartupWMClass=libreoffice-impress
X-KDE-Protocols=file,http,smb,ftp,webdav
---

Bu işlemlerden sonra odp formatındaki dosyaya sağ tıkladığımda aşağıdaki görüntüyü gördüm:


6 Ocak 2015 Salı

Bir Git Deposuna Başka Bir Git Deposunu Geçmişiyle Taşımak

Diyelim ki git deposunda geliştirdiğiniz projenizi başka bir git deposunun içindeki bir yere taşımanız gerekti. (Transfer işleminden bahsetmiyorum.) Ve kendi deponuzdayken yaptığınız commitlerin de kaybolmasını istemiyorsunuz. Öyleyse sırayla aşağıdaki adımları takip edmelisiniz:

$git clone kendi_depom
$git clone hedef_depo
$cd hedef_depo
$git checkout master
$git remote add rm1remote <kendi_depomun_urlsi>
$git fetch rm1remote
$git merge rm1remote/master
$git remote rm rm1remote

3 Ocak 2015 Cumartesi

Python Uygulamalarına Dil Desteği Eklemek

Projemiz klasik olarak ekrana "Hello World"  yazdırsın ve buna dil desteği ekleyelim. Projenin dizin yapısı şöyle:
---
helloproject/
└── hello.py

---
hello.py dosyasının içeriği aşağıda:

---
print "Hello World"
---


1. _() Fonsiyonunu Belirlemek

Bu fonksiyon kodun içinde çevirilecek cümlelerin, kelimelerin belirlenmesine ve yerelimizde kullandığımız dil her ne ise cümlelerin o dile göre çevirilmiş halinin gösterilmesine yarayan fonksiyondur.

hello.py dosyası ile aynı dizine i18n.py isimli bir dosya açalım ve içine şunları yazalım.

---

# -*- coding: utf-8 -*-

import os, sys
import locale
import gettext

# Bu degisken ismine kendi uygulamanizin ismini yazmalısınız!
# Ceviri dosyaları bu yolda olmalıdır.
#  @LOCALE_DIR@/@LANGUAGE@/LC_MESSAGES/@APP_NAME@.mo
APP_NAME = "helloproject"



# Sisteminizde helloproject isim dosyanın bulunduğu yolu döndürecektir.

# Bu kismi baska projeler icin projenizin bulunduğu dizine göre değiştirmelisiniz.
APP_DIR = os.path.dirname(os.path.abspath("helloproject"))

# .mo dosyalari bu dizinin altinda olacaktir APP_Dir/i18n/LANGUAGECODE/LC_MESSAGES/

LOCALE_DIR = os.path.join(APP_DIR, 'i18n')

# Hangi dile cevrilecegini belirleyen kisim burasidir. Burada olusan
# listede ilk yazan dil hangisiyse ona ceviri yapilacaktir.
#
# hangi dile cevirilecegi LANG cevresel degiskenine bakilarak belirlenir.
DEFAULT_LANGUAGES = os.environ.get('LANG', '').split('.')
DEFAULT_LANGUAGES += ['en_US']

lc, encoding = locale.getdefaultlocale()
if lc:
    languages = [lc]

languages += DEFAULT_LANGUAGES
mo_location = LOCALE_DIR

# Burada herhangi bir degisiklik yapmaniza gerek yok
gettext.install(True, localedir=None, unicode=1)

gettext.find(APP_NAME, mo_location)

gettext.textdomain (APP_NAME)

gettext.bind_textdomain_codeset(APP_NAME, "UTF-8")

---

Şuan oluşan dizin yapısı:

---
 helloproject/
├── hello.py
└── i18n.py

---
2. Çevirmek İstediğimiz  Cümleleri Belirlemek

İçinde çeviri yapmak istediğimiz dosyaların başına şu kodu eklemeliyiz.

---
import i18n
_ = i18n.language.ugettext 
---

Bu projede çevrilecek tek cümle "Hello World" oluğundan şimdi hello.py dosyasını aşağıdaki şekilde düzenleyelim.


---
import i18n
_ = i18n.language.ugettext 
 
print _("Hello World")
---

Çevilecek cümleler şu yapıda olmalı:

_("çevrilecek cümle")

3.Çeviriler İçin Şablon Oluşturmak

.pot uzantılı dosya şablon dosyasıdır. Her projede bir tane .pot uzantılı dosya bulunur. Çeviri yapılacak diller için oluşturulacak dosyalar bu .pot uzantılı dosya kullanılarak üretilecektir.

Şimdi helloproject.pot isimli dosyayı oluşturacağız. Önce projenin içine "po" isminde bir dizin oluşturalım ve aşağıdaki komutu çalıştıralım.

---
xgettext --language=Python --keyword=_ --output=po/helloproject.pot hello.py
---

Eğer "xgettext: Non-ASCII character at..." gibi bir hatayla karşılaşıyorsanız -başka projelerde- aşağıdaki komutu yazmalısınız:

---
xgettext --language=Python --keyword=_ --output=po/helloproject.pot --from-code=UTF-8 hello.py
---

Bu adımdan sonra oluşan dizin yapısı şu şekildedir:

---
 helloproject/
├── hello.py
├── i18n.py
└── po
    └── helloproject.pot

---

Oluşan helloproject.pot isimli dosya aşağıdaki gibi olmalı:

---
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-01-03 22:53+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"

#: hello.py:4
msgid "Hello World"
msgstr ""

---

! Buradaki isim soyisim email gibi bilgileri doldurmakta fayda var.

4. Bir Dil İçin Çeviri Dosyası Oluşturmak

Oluşturduğumuz bu şablon dosyasını kullanarak projenin türkçe için çeviri dosyasını oluşturacağız. Oluşturduğumuz po dizininin içinde aşağıdaki komutu çalıştıralım

---
msginit --input=helloproject.pot --locale=tr_TR
---

Bu işlemin sonunda oluşan dizin yapısı:

---
helloproject/
├── hello.py
├── i18n.py
└── po
    ├── helloproject.pot
    └── tr.po

---

Oluşan tr.po dosyasının içi şöyle olmalı:

---
# Turkish translations for PACKAGE package.
# Copyright (C) 2015 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# gulsah <gulsah.1004@gmail.com>, 2015.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-01-03 22:53+0200\n"
"PO-Revision-Date: 2015-01-03 23:08+0200\n"
"Last-Translator: gulsah <gulsah.1004@gmail.com>\n"
"Language-Team: Turkish\n"
"Language: tr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=ASCII\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#: hello.py:4
msgid "Hello World"
msgstr "
"
---


Burada .po uzantılı dosyaları çevirmek için çeşitli editörler var (poEdit ,pootle, transifex,...) Bizim projemiz minik olduğundan elle çeviriyi yapabiliriz. Çeviriyi yaptığımızda dosyanın son 2 satırı şöyle değişecek:

---
msgid "Hello World"
msgstr "Merhaba Dunya
"
---

5. Derleme

Program hızlı çalışabilmesi açısından oluşturduğumuz bu .po dosyalarına değil bunları derleyerek oluşturduğumuz .mo dosyalarına bakacaktır. Bu derleme işi ve derlenen dosyaları koyduğumuz yer program için önemli. i18n.py içinde belirttiğimiz şekilde bu proje için oluşan .mo dosyalarını aşağıdaki komutla oluşturacağımız dizin içinde saklayacağız. (Şuan helloproject dizini içindeyiz)

---
mkdir -p i18n/tr/LC_MESSAGES
---

Şimdi tr.po dosyasını derleyelim:

---
msgfmt po/tr.po --output-file i18n/tr/LC_MESSAGES/helloproject.mo
---

Sonuçta oluşan dizin yapısı şöyle olmalıdır:

---
helloproject/
├── hello.py
├── i18n
│   └── tr
│       └── LC_MESSAGES
│           └── helloproject.mo
├── i18n.py
└── po
    ├── helloproject.pot
    └── tr.po

---

Eğer LANG değişkenin içinde kullandığınız dil ingilizceyse onu türkçe ile değiştirirseniz hello.py dosyasını çalıştırdığınızda artık çıktısının "Merhaba Dunya" olduğunu göreceksiniz.