tr-acikveri 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. tr_acikveri-0.1.0/CHANGELOG.md +27 -0
  2. tr_acikveri-0.1.0/CITATION.cff +21 -0
  3. tr_acikveri-0.1.0/LICENSE +21 -0
  4. tr_acikveri-0.1.0/MANIFEST.in +9 -0
  5. tr_acikveri-0.1.0/PKG-INFO +313 -0
  6. tr_acikveri-0.1.0/README.md +267 -0
  7. tr_acikveri-0.1.0/examples/quickstart.py +38 -0
  8. tr_acikveri-0.1.0/pyproject.toml +126 -0
  9. tr_acikveri-0.1.0/setup.cfg +4 -0
  10. tr_acikveri-0.1.0/src/tr_acikveri/__init__.py +99 -0
  11. tr_acikveri-0.1.0/src/tr_acikveri/__main__.py +7 -0
  12. tr_acikveri-0.1.0/src/tr_acikveri/_version.py +1 -0
  13. tr_acikveri-0.1.0/src/tr_acikveri/cache.py +119 -0
  14. tr_acikveri-0.1.0/src/tr_acikveri/ckan.py +268 -0
  15. tr_acikveri-0.1.0/src/tr_acikveri/cli.py +366 -0
  16. tr_acikveri-0.1.0/src/tr_acikveri/client.py +309 -0
  17. tr_acikveri-0.1.0/src/tr_acikveri/errors.py +54 -0
  18. tr_acikveri-0.1.0/src/tr_acikveri/http.py +374 -0
  19. tr_acikveri-0.1.0/src/tr_acikveri/models.py +308 -0
  20. tr_acikveri-0.1.0/src/tr_acikveri/portals.py +391 -0
  21. tr_acikveri-0.1.0/src/tr_acikveri/py.typed +0 -0
  22. tr_acikveri-0.1.0/src/tr_acikveri/readers.py +362 -0
  23. tr_acikveri-0.1.0/src/tr_acikveri.egg-info/PKG-INFO +313 -0
  24. tr_acikveri-0.1.0/src/tr_acikveri.egg-info/SOURCES.txt +35 -0
  25. tr_acikveri-0.1.0/src/tr_acikveri.egg-info/dependency_links.txt +1 -0
  26. tr_acikveri-0.1.0/src/tr_acikveri.egg-info/entry_points.txt +2 -0
  27. tr_acikveri-0.1.0/src/tr_acikveri.egg-info/requires.txt +19 -0
  28. tr_acikveri-0.1.0/src/tr_acikveri.egg-info/top_level.txt +1 -0
  29. tr_acikveri-0.1.0/tests/conftest.py +70 -0
  30. tr_acikveri-0.1.0/tests/mockserver.py +423 -0
  31. tr_acikveri-0.1.0/tests/test_ckan.py +175 -0
  32. tr_acikveri-0.1.0/tests/test_cli.py +193 -0
  33. tr_acikveri-0.1.0/tests/test_client.py +147 -0
  34. tr_acikveri-0.1.0/tests/test_http.py +199 -0
  35. tr_acikveri-0.1.0/tests/test_models.py +103 -0
  36. tr_acikveri-0.1.0/tests/test_portals.py +115 -0
  37. tr_acikveri-0.1.0/tests/test_readers.py +242 -0
@@ -0,0 +1,27 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [Unreleased]
6
+
7
+ ## [0.1.0] - 2026-11-09
8
+ ### Added
9
+ - Portal registry (`list_portals`, `get_portal`, `register_portal`) with 13 CKAN
10
+ portals verified on 2026-11-09 (İBB, İzmir, Konya, Gaziantep, Balıkesir, Denizli,
11
+ Trabzon, Manisa, Çanakkale, Bursa Açık Yeşil, Kadıköy, Tuzla, Nilüfer) and
12
+ non-CKAN / unreachable portals listed as unsupported; licence notes per portal;
13
+ lookup by key, alias, city name (Turkish letters folded) or any CKAN URL.
14
+ - `CkanClient` for the CKAN Action API v3 (GET only): `package_search` with format,
15
+ organization and tag filters, paging iterator, `package_show`, `resource_show`,
16
+ `organization_list`, `tag_list`, `license_list`, `datastore_search`.
17
+ - `AcikVeri` multi-portal client: parallel search across portals with per-portal
18
+ error reporting, resource listing filtered by normalised format (CSV, GeoJSON,
19
+ SHP, XLSX ...), downloads into an on-disk cache with provenance sidecar.
20
+ - Polite HTTP: `tr-acikveri/<version>` User-Agent with optional contact, per-host rate
21
+ limit, timeouts, retries with exponential backoff and `Retry-After`, resumable
22
+ downloads via HTTP `Range`, size limit, certifi-aware TLS context.
23
+ - Readers: encoding detection (UTF-8 BOM, UTF-8, cp1254, ISO-8859-9), delimiter
24
+ sniffing (`;` first), Turkish number parsing, GeoJSON with legacy `crs` member;
25
+ optional pandas / openpyxl / geopandas helpers.
26
+ - Turkish CLI `tr-acikveri` with `portallar`, `ara`, `bilgi`, `indir`, `kurumlar`,
27
+ `etiketler`.
@@ -0,0 +1,21 @@
1
+ cff-version: 1.2.0
2
+ message: "If you use this software, please cite it as below."
3
+ authors:
4
+ - family-names: "Eminoğlu"
5
+ given-names: "Yusuf"
6
+ email: "geospacephilo@gmail.com"
7
+ orcid: "https://orcid.org/0009-0005-6000-2934"
8
+ title: "tr-acikveri"
9
+ version: "0.1.0"
10
+ date-released: "2026-11-09"
11
+ license: "MIT"
12
+ repository-code: "https://github.com/YusufEminoglu/tr_acikveri_sdk"
13
+ url: "https://pypi.org/project/tr-acikveri/"
14
+ abstract: "One Python client for Turkish public open-data portals running CKAN (İBB, İzmir, Konya, Gaziantep and others): multi-portal dataset search, metadata and resource listing by format, polite cached and resumable downloads, and readers for cp1254 / UTF-8 BOM, semicolon-delimited CSV and GeoJSON, with a Turkish command-line interface."
15
+ keywords:
16
+ - open data
17
+ - açık veri
18
+ - CKAN
19
+ - Türkiye
20
+ - municipality
21
+ - GIS
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Yusuf Eminoğlu
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,9 @@
1
+ include LICENSE
2
+ include README.md
3
+ include CHANGELOG.md
4
+ include CITATION.cff
5
+ include pyproject.toml
6
+ include src/tr_acikveri/py.typed
7
+ recursive-include src/tr_acikveri *.py
8
+ recursive-include tests *.py
9
+ recursive-include examples *.py
@@ -0,0 +1,313 @@
1
+ Metadata-Version: 2.4
2
+ Name: tr-acikveri
3
+ Version: 0.1.0
4
+ Summary: Türkiye açık veri portalları (CKAN) için tek istemci: çoklu portal arama, veri seti bilgisi, kibar ve sürdürülebilir indirme, cp1254/UTF-8 BOM ve ; ayraçlı CSV ile GeoJSON okuma, Türkçe CLI.
5
+ Author-email: Yusuf Eminoğlu <geospacephilo@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/YusufEminoglu/tr_acikveri_sdk
8
+ Project-URL: Repository, https://github.com/YusufEminoglu/tr_acikveri_sdk
9
+ Project-URL: Issues, https://github.com/YusufEminoglu/tr_acikveri_sdk/issues
10
+ Project-URL: Changelog, https://github.com/YusufEminoglu/tr_acikveri_sdk/blob/main/CHANGELOG.md
11
+ Keywords: open-data,acik-veri,ckan,turkey,turkiye,istanbul,izmir,municipality,csv,geojson,gis,urban-planning
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Operating System :: OS Independent
20
+ Classifier: Environment :: Console
21
+ Classifier: Natural Language :: Turkish
22
+ Classifier: Topic :: Scientific/Engineering :: GIS
23
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
24
+ Classifier: Topic :: Internet :: WWW/HTTP
25
+ Classifier: Intended Audience :: Science/Research
26
+ Classifier: Intended Audience :: Developers
27
+ Classifier: Typing :: Typed
28
+ Requires-Python: >=3.9
29
+ Description-Content-Type: text/markdown
30
+ License-File: LICENSE
31
+ Provides-Extra: pandas
32
+ Requires-Dist: pandas>=1.3.0; extra == "pandas"
33
+ Provides-Extra: excel
34
+ Requires-Dist: pandas>=1.3.0; extra == "excel"
35
+ Requires-Dist: openpyxl>=3.0.0; extra == "excel"
36
+ Provides-Extra: geo
37
+ Requires-Dist: geopandas>=0.10.0; extra == "geo"
38
+ Provides-Extra: certifi
39
+ Requires-Dist: certifi; extra == "certifi"
40
+ Provides-Extra: dev
41
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
42
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
43
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
44
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
45
+ Dynamic: license-file
46
+
47
+ # tr-acikveri
48
+
49
+ [![PyPI version](https://img.shields.io/pypi/v/tr-acikveri.svg)](https://pypi.org/project/tr-acikveri/)
50
+ [![Python versions](https://img.shields.io/pypi/pyversions/tr-acikveri.svg)](https://pypi.org/project/tr-acikveri/)
51
+ [![CI](https://github.com/YusufEminoglu/tr_acikveri_sdk/actions/workflows/ci.yml/badge.svg)](https://github.com/YusufEminoglu/tr_acikveri_sdk/actions/workflows/ci.yml)
52
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
53
+
54
+ **English summary.** `tr-acikveri` is one Python client for Turkish public open-data
55
+ portals that run CKAN (Istanbul İBB, İzmir, Konya, Gaziantep, Manisa, Trabzon and
56
+ others): search datasets across many portals, inspect metadata, list resources by
57
+ format, and download them politely with caching, rate limiting, retries and resume.
58
+ It reads the CSV files these portals actually publish (Windows-1254 or UTF-8 with BOM,
59
+ `;` delimiters, decimal commas) and GeoJSON, ships a Turkish CLI, and reminds you that
60
+ every dataset's licence belongs to the publishing portal.
61
+
62
+ ---
63
+
64
+ **Türkiye'deki açık veri portalları için tek istemci.**
65
+
66
+ Belediyelerin ve kurumların açık veri portallarının çoğu
67
+ [CKAN](https://ckan.org) üzerinde çalışır ve aynı *CKAN Action API*'sini sunar.
68
+ `tr-acikveri` bu portalları tek bir arayüzün arkasına koyar:
69
+
70
+ - Bir veya birden çok portalda **veri seti arama** (portallar paralel sorgulanır,
71
+ hata veren portal aramayı durdurmaz).
72
+ - **Kurum, etiket, veri seti bilgisi** ve **biçime göre kaynak listeleme**
73
+ (CSV, GeoJSON, SHP, XLSX, KML ...; portalların tutarsız biçim adları normalleştirilir).
74
+ - **Kibar indirme:** `tr-acikveri/<sürüm>` User-Agent'ı, sunucu başına hız sınırı,
75
+ zaman aşımı, `Retry-After` dikkate alan yeniden deneme, diskte önbellek ve
76
+ yarıda kalan indirmeyi **kaldığı yerden sürdürme** (HTTP `Range`).
77
+ - **Türkçe dosyalar:** cp1254 / UTF-8 BOM kodlama tespiti, `;` ayraç tespiti,
78
+ `1.234,56` gibi sayıların okunması, eski `crs` alanlı GeoJSON (ör. EPSG:5254).
79
+ - İsteğe bağlı **pandas / geopandas** dönüşümleri ve Türkçe **komut satırı** (`ara`,
80
+ `bilgi`, `indir`, `portallar`, `kurumlar`, `etiketler`).
81
+
82
+ Yalnızca Python standart kütüphanesiyle çalışır; Python 3.9 ve üstü gerekir.
83
+
84
+ > **Lisans uyarısı.** Bu paket MIT lisanslıdır, ancak **indirdiğiniz verilerin lisansı
85
+ > her portala ve veriyi yayımlayan kuruma aittir** (İBB Açık Veri Lisansı, İzmir BB Açık
86
+ > Veri Lisansı, CC BY 4.0, CC BY-NC ...). Paket size veriler üzerinde hiçbir hak
87
+ > vermez. Her veri setinin lisansını (`bilgi` komutu veya `Dataset.license_title`)
88
+ > okuyun, koşullarına uyun ve kaynak gösterin. Ticari olmayan (NC) lisanslara özellikle
89
+ > dikkat edin.
90
+
91
+ ## Kurulum
92
+
93
+ ```bash
94
+ pip install tr-acikveri # yalnızca standart kütüphane
95
+ pip install "tr-acikveri[pandas]" # + DataFrame dönüşümü
96
+ pip install "tr-acikveri[excel]" # + XLSX/XLS okuma (pandas + openpyxl)
97
+ pip install "tr-acikveri[geo]" # + GeoDataFrame (geopandas)
98
+ pip install "tr-acikveri[certifi]" # + Mozilla CA paketi (bkz. "TLS sertifikaları")
99
+ ```
100
+
101
+ ## Hızlı başlangıç (komut satırı)
102
+
103
+ ```bash
104
+ tr-acikveri portallar # CKAN portalları
105
+ tr-acikveri portallar --hepsi # CKAN olmayanlar dahil
106
+ tr-acikveri ara otopark -p ibb -p izmir -f csv -n 5
107
+ tr-acikveri bilgi ibb ispark-otopark-bilgileri
108
+ tr-acikveri indir konya otopark-bilgileri -f csv -o veri/
109
+ tr-acikveri kurumlar izmir --json
110
+ ```
111
+
112
+ Örnek çıktı (kısaltılmış, 2026-11-09):
113
+
114
+ ```
115
+ [konya] otopark-bilgileri
116
+ Otopark Bilgileri (CSV) · Destek Hizmetleri Dairesi Başkanlığı
117
+ [izmir] otopark-ucretleri
118
+ Otopark Ücretleri (CSV, XLSX) · İZELMAN A.Ş.
119
+
120
+ Toplam eşleşme 3 (izmir: 2; konya: 1); gösterilen 3.
121
+ ```
122
+
123
+ Ortak seçenekler: `--onbellek KLASÖR`, `--onbellek-suresi SN`, `--onbelleksiz`,
124
+ `--zaman-asimi SN`, `--aralik SN` (aynı sunucuya iki istek arası, varsayılan 1 sn),
125
+ `--yeniden-deneme N`, `--iletisim E-POSTA` (User-Agent'a eklenir), `--json`.
126
+ `-p` portal anahtarı, şehir adı (`İzmir`, `istanbul`) veya herhangi bir CKAN adresi
127
+ olabilir. Yönlendirilen çıktı (ör. `> sonuc.json`) her zaman UTF-8 yazılır.
128
+
129
+ ## Hızlı başlangıç (Python)
130
+
131
+ ```python
132
+ from tr_acikveri import AcikVeri
133
+
134
+ av = AcikVeri(contact="ad.soyad@kurum.edu.tr") # iletişim adresi önerilir
135
+
136
+ sonuc = av.search("otopark", portals=["ibb", "izmir", "konya"], formats=["csv"], rows=5)
137
+ for ds in sonuc:
138
+ print(ds.portal, ds.name, ds.formats, ds.license_title)
139
+ print(sonuc.counts, sonuc.errors)
140
+
141
+ ds = av.dataset("konya", "otopark-bilgileri")
142
+ kaynak = ds.resources_by_format(["csv"])[0]
143
+ tablo = av.read_csv(kaynak) # indirir (önbellek) ve okur
144
+ print(tablo.encoding, tablo.delimiter, tablo.columns)
145
+ kapasite = tablo.numeric("bolgekapasite") # "1.250" -> 1250.0
146
+
147
+ df = av.to_dataframe(kaynak, numeric=True) # [pandas]
148
+
149
+ parklar = av.search("park", portals=["trabzon"], formats=["geojson"]).datasets[0]
150
+ geo_kaynak = parklar.resources_by_format(["geojson"])[0]
151
+ geo = av.read_geojson(geo_kaynak) # FeatureCollection dict
152
+ gdf = av.to_geodataframe(geo_kaynak) # [geo]
153
+ ```
154
+
155
+ Tek portal için alt düzey istemci:
156
+
157
+ ```python
158
+ from tr_acikveri import CkanClient
159
+
160
+ ibb = CkanClient("ibb")
161
+ sayi, sayfa = ibb.search("bisiklet", formats=["geojson"], sort="metadata_modified desc")
162
+ for ds in ibb.iter_search("hava kalitesi", limit=200):
163
+ ...
164
+ kayitlar = ibb.datastore_search(resource_id, limit=100, filters={"ilce": "Kadıköy"})
165
+ ```
166
+
167
+ ## Portal kaydı
168
+
169
+ Her kayıt 2026-11-09 tarihinde `<adres>/api/3/action/status_show` adresine yapılan tek
170
+ bir salt okunur `GET` isteğiyle doğrulandı; lisans notları portalın `license_list`
171
+ ve `package_search` yanıtlarından alındı. Veri seti sayıları aynı tarihe aittir.
172
+
173
+ | Anahtar | Portal | Adres | Veri seti | Lisans (portalın bildirdiği) |
174
+ |---|---|---|---:|---|
175
+ | `ibb` | İstanbul BB | https://data.ibb.gov.tr | 565 | İBB Açık Veri Lisansı |
176
+ | `izmir` | İzmir BB | https://acikveri.bizizmir.com | 251 | İzmir BB Açık Veri Lisansı; bazıları CC BY / belirtilmemiş |
177
+ | `konya` | Konya BB | https://acikveri.konya.bel.tr | 233 | CC BY 4.0 |
178
+ | `gaziantep` | Gaziantep | https://acikveri.gaziantep.bel.tr | 252 | Gaziantep Açık Veri Lisansı |
179
+ | `balikesir` | Balıkesir BB | https://acikveri.balikesir.bel.tr | 252 | Balıkesir Açık Veri Lisansı |
180
+ | `denizli` | Denizli | https://acikveri.denizli.bel.tr | 39 | Denizli Açık Veri Lisansı |
181
+ | `trabzon` | Trabzon BB | https://acikveri.trabzon.bel.tr | 206 | Trabzon Açık Veri Lisansı |
182
+ | `manisa` | Manisa BB | https://acikveri.manisa.bel.tr | 1389 | Manisa BB Açık Veri Lisansı (mbb-odl-1.0) |
183
+ | `canakkale` | Çanakkale | https://acikveri.canakkale.bel.tr | 123 | Çanakkale Açık Veri Lisansı |
184
+ | `bursa-yesil` | Bursa Açık Yeşil | https://acikyesil.bursa.bel.tr | 49 | kurum lisansı (yalnızca yeşil alan verisi) |
185
+ | `kadikoy` | Kadıköy (ilçe) | https://acikveri.kadikoy.bel.tr | 161 | karışık: CC BY, CC BY-NC, CC BY-ND |
186
+ | `tuzla` | Tuzla (ilçe) | https://veri.tuzla.bel.tr | 91 | CC BY |
187
+ | `nilufer` | Nilüfer (ilçe) | https://acikveri.nilufer.bel.tr | 65 | çoğunda belirtilmemiş; bazıları CC BY / CC BY-NC |
188
+
189
+ Desteklenmeyen (CKAN API'si yok veya kontrol sırasında erişilemedi) ve
190
+ `portallar --hepsi` ile listelenenler: Ankara (seffaf.ankara.bel.tr), Kocaeli
191
+ (veri.kocaeli.bel.tr), Kayseri, Küçükçekmece, Sağlık Bakanlığı (özel yazılım);
192
+ Antalya, Sakarya ve ULASAV (ulasav.csb.gov.tr; erişilemedi, API türü doğrulanamadı).
193
+ Gaziantep, Denizli, Trabzon, Çanakkale, Balıkesir ve Bursa Açık Yeşil portalları
194
+ `ulasav-license` kimlikli ortak CKAN şablonunu kullanır; lisans metni her portalın
195
+ `/license` sayfasındadır.
196
+
197
+ Kayıtta olmayan bir CKAN portalı adresle kullanılabilir veya kaydedilebilir:
198
+
199
+ ```python
200
+ from tr_acikveri import Portal, register_portal, CkanClient
201
+
202
+ CkanClient("https://acikveri.ornek.bel.tr").search("imar")
203
+ register_portal(Portal("ornek", "Örnek Belediyesi", "https://acikveri.ornek.bel.tr",
204
+ city="Örnek", license_note="CC BY 4.0"))
205
+ ```
206
+
207
+ Portallar değişir: adres taşınabilir, API kapanabilir. Kayıttaki bilgiler kontrol
208
+ tarihindeki durumu yansıtır.
209
+
210
+ ## API özeti
211
+
212
+ | Nesne | Açıklama |
213
+ |---|---|
214
+ | `AcikVeri(portals=None, cache_dir=None, cache_ttl=86400, contact=None, timeout=30, min_interval=1.0, retries=3, max_workers=4)` | Çok portallı istemci |
215
+ | `.search(query, portals, formats, rows, organization, tags, sort)` → `SearchResult` | `datasets`, `counts`, `errors`, `total` |
216
+ | `.dataset(portal, ad)` → `Dataset`; `.resources(portal, ad, formats)` → `[Resource]` | Meta veri ve kaynaklar |
217
+ | `.organizations(portal)`, `.tags(portal, query)` | Kurumlar, etiketler |
218
+ | `.download(resource, dest=None, overwrite, resume, max_bytes, progress)` → `Path` | Önbelleğe veya hedefe indirme; `.meta.json` kaynak bilgisi |
219
+ | `.download_dataset(portal, ad, formats, dest_dir)` | Veri setinin tüm dosyaları |
220
+ | `.read_csv`, `.read_geojson`, `.load`, `.to_dataframe`, `.to_geodataframe` | Okuma |
221
+ | `CkanClient(portal)` | `search`, `iter_search`, `dataset`, `resource`, `organizations`, `tags`, `licenses`, `datastore_search`, `action` |
222
+ | `list_portals`, `get_portal`, `register_portal`, `Portal` | Portal kaydı |
223
+ | `read_csv`, `CsvTable`, `detect_encoding`, `sniff_delimiter`, `parse_number`, `read_geojson`, `geojson_crs` | Dosya okuyucular |
224
+ | `HttpClient`, `RetryPolicy`, `RateLimiter`, `Cache` | Taşıma katmanı |
225
+ | `AcikVeriError` → `HttpError`, `TransportError`, `CkanError` → `NotFoundError`, `UnsupportedPortalError`, `PortalNotFoundError`, `FormatError`, `MissingDependencyError` | Hatalar |
226
+
227
+ ## Yöntem ve kaynaklar
228
+
229
+ - **CKAN Action API v3** — yalnızca okuma eylemleri (`status_show`, `package_search`,
230
+ `package_show`, `resource_show`, `organization_list`, `tag_list`, `license_list`,
231
+ `datastore_search`), hepsi `GET` ile. Kaynak: CKAN API belgeleri,
232
+ https://docs.ckan.org/en/2.9/api/. `package_search` için `rows` en fazla 1000'e
233
+ sınırlanır (CKAN'ın `ckan.search.rows_max` varsayılanı).
234
+ - **Biçim filtresi** — `res_format` Solr'da birebir eşleşen bir alan olduğundan,
235
+ portallarda görülen yazımların tamamı (`CSV`, `csv`, `.csv`, `GeoJSON`, `.shp`,
236
+ `Excel` ...) sunucuya gönderilir; sonuç ayrıca istemci tarafında normalleştirilmiş
237
+ biçimle süzülür.
238
+ - **HTTP** — `Retry-After` (saniye veya HTTP tarihi) ve `Range`/`Content-Range`
239
+ ile sürdürme: RFC 9110 §10.2.3 ve §14. Yeniden deneme 408/425/429/5xx ve ağ
240
+ hatalarında, üstel bekleme (+%10 rastgele) ile yapılır. Hız sınırı sunucu (host)
241
+ başınadır ve iş parçacıkları arasında paylaşılır.
242
+ - **Kodlama** — sıra: UTF-8 BOM → UTF-16 BOM → katı UTF-8 → Windows-1254 (cp1254,
243
+ Türkçe Windows kod sayfası) → ISO-8859-9. Ayraç, ilk 50 satırda en tutarlı sütun
244
+ sayısını veren adaydır (`;`, `,`, sekme, `|`; eşitlikte `;`).
245
+ - **Sayılar** — `parse_number` Türkçe yazımı (ondalık virgül, binlik nokta) varsayar;
246
+ yalnızca nokta içeren ve binlik gruplamaya uymayan değerler (`12.5`) ondalık
247
+ okunur. `%`, `TL`, `₺` ve boşluklar yok sayılır.
248
+ - **GeoJSON** — RFC 7946 (WGS 84, `EPSG:4326`). 2008 GeoJSON belirtimindeki `crs`
249
+ alanı varsa (`urn:ogc:def:crs:EPSG::5254` gibi) `geojson_crs` bu kodu döndürür ve
250
+ `to_geodataframe` onu kullanır.
251
+
252
+ ## TLS sertifikaları
253
+
254
+ Sertifika doğrulaması her zaman açıktır. Bazı portallar (kontrol tarihinde
255
+ `data.ibb.gov.tr`) Windows'un yalnızca gerektiğinde indirdiği bir kök sertifikaya
256
+ zincirlenir; Python bu durumda `CERTIFICATE_VERIFY_FAILED` hatası verir.
257
+ `certifi` kuruluysa (`pip install "tr-acikveri[certifi]"`) paket otomatik olarak
258
+ Mozilla CA paketini kullanır. Alternatifler: `SSL_CERT_FILE` ortam değişkeni,
259
+ `HttpClient(ca_file=...)` veya `HttpClient(ssl_context=...)`.
260
+
261
+ ## Önbellek
262
+
263
+ Varsayılan klasör `TR_ACIKVERI_CACHE` ortam değişkeni, yoksa Windows'ta
264
+ `%LOCALAPPDATA%\tr-acikveri`, diğer sistemlerde `~/.cache/tr-acikveri`'dir.
265
+ API yanıtları `api/` altında (varsayılan 1 gün), indirilen dosyalar
266
+ `files/<portal>/<kaynak kimliği>/` altında tutulur. Her dosyanın yanında kaynak
267
+ adresi, portal, veri seti, indirme zamanı ve HTTP doğrulayıcılarını içeren bir
268
+ `.meta.json` bulunur. İndirilen verileri bir git deposuna eklemeyin.
269
+
270
+ ## Sınırlamalar
271
+
272
+ - Yalnızca CKAN portalları desteklenir; özel yazılımlı portallar (Ankara, Kocaeli,
273
+ Kayseri, Sağlık Bakanlığı ...) kayıtta yalnızca bilgi amaçlıdır.
274
+ - Portal listesi, veri seti sayıları ve lisans notları 2026-11-09 tarihli kontrollere
275
+ dayanır; değişebilir. Bağlayıcı olan, veri setinin portaldaki lisansıdır.
276
+ - Kodlama tespiti sezgiseldir: UTF-8 olarak geçerli olan cp1254 dosyaları (çok nadir)
277
+ UTF-8 sayılır; gerekirse `encoding="cp1254"` verin.
278
+ - `API`/`HTML` türündeki kaynaklar dosya değildir ve varsayılan olarak indirilmez.
279
+ - Çok portallı aramada `rows` portal başına uygulanır; sonuçlar portallar arasında
280
+ yeniden sıralanmaz.
281
+ - Önbellekteki dosya, sunucuda güncellense bile `overwrite=True` (CLI: `--yeniden`)
282
+ verilmedikçe yeniden indirilmez.
283
+
284
+ ## Geliştirme
285
+
286
+ ```bash
287
+ pip install -e ".[dev,pandas]"
288
+ pytest --cov=tr_acikveri
289
+ ruff check . && ruff format --check src tests && mypy src
290
+ ```
291
+
292
+ Testler gerçek ağa hiç çıkmaz: `tests/mockserver.py` iki CKAN portalını, hatalı
293
+ portalları (500, HTML), 429/503 yanıtlarını, bağlantısı yarıda kopan indirmeleri ve
294
+ `Range` desteği olmayan sunucuları taklit eden yerel bir HTTP sunucusudur.
295
+
296
+ ## Lisans
297
+
298
+ MIT © 2026 Yusuf Eminoğlu. Bkz. [LICENSE](LICENSE). Bu lisans yalnızca yazılımı
299
+ kapsar; portallardan alınan veriler kendi lisanslarına tabidir.
300
+
301
+ ## Academic citation
302
+
303
+ ```bibtex
304
+ @software{eminoglu_tr_acikveri,
305
+ author = {Eminoğlu, Yusuf},
306
+ title = {tr-acikveri},
307
+ year = {2026},
308
+ version = {0.1.0},
309
+ url = {https://github.com/YusufEminoglu/tr_acikveri_sdk}
310
+ }
311
+ ```
312
+
313
+ Ayrıca bkz. `CITATION.cff`.
@@ -0,0 +1,267 @@
1
+ # tr-acikveri
2
+
3
+ [![PyPI version](https://img.shields.io/pypi/v/tr-acikveri.svg)](https://pypi.org/project/tr-acikveri/)
4
+ [![Python versions](https://img.shields.io/pypi/pyversions/tr-acikveri.svg)](https://pypi.org/project/tr-acikveri/)
5
+ [![CI](https://github.com/YusufEminoglu/tr_acikveri_sdk/actions/workflows/ci.yml/badge.svg)](https://github.com/YusufEminoglu/tr_acikveri_sdk/actions/workflows/ci.yml)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
7
+
8
+ **English summary.** `tr-acikveri` is one Python client for Turkish public open-data
9
+ portals that run CKAN (Istanbul İBB, İzmir, Konya, Gaziantep, Manisa, Trabzon and
10
+ others): search datasets across many portals, inspect metadata, list resources by
11
+ format, and download them politely with caching, rate limiting, retries and resume.
12
+ It reads the CSV files these portals actually publish (Windows-1254 or UTF-8 with BOM,
13
+ `;` delimiters, decimal commas) and GeoJSON, ships a Turkish CLI, and reminds you that
14
+ every dataset's licence belongs to the publishing portal.
15
+
16
+ ---
17
+
18
+ **Türkiye'deki açık veri portalları için tek istemci.**
19
+
20
+ Belediyelerin ve kurumların açık veri portallarının çoğu
21
+ [CKAN](https://ckan.org) üzerinde çalışır ve aynı *CKAN Action API*'sini sunar.
22
+ `tr-acikveri` bu portalları tek bir arayüzün arkasına koyar:
23
+
24
+ - Bir veya birden çok portalda **veri seti arama** (portallar paralel sorgulanır,
25
+ hata veren portal aramayı durdurmaz).
26
+ - **Kurum, etiket, veri seti bilgisi** ve **biçime göre kaynak listeleme**
27
+ (CSV, GeoJSON, SHP, XLSX, KML ...; portalların tutarsız biçim adları normalleştirilir).
28
+ - **Kibar indirme:** `tr-acikveri/<sürüm>` User-Agent'ı, sunucu başına hız sınırı,
29
+ zaman aşımı, `Retry-After` dikkate alan yeniden deneme, diskte önbellek ve
30
+ yarıda kalan indirmeyi **kaldığı yerden sürdürme** (HTTP `Range`).
31
+ - **Türkçe dosyalar:** cp1254 / UTF-8 BOM kodlama tespiti, `;` ayraç tespiti,
32
+ `1.234,56` gibi sayıların okunması, eski `crs` alanlı GeoJSON (ör. EPSG:5254).
33
+ - İsteğe bağlı **pandas / geopandas** dönüşümleri ve Türkçe **komut satırı** (`ara`,
34
+ `bilgi`, `indir`, `portallar`, `kurumlar`, `etiketler`).
35
+
36
+ Yalnızca Python standart kütüphanesiyle çalışır; Python 3.9 ve üstü gerekir.
37
+
38
+ > **Lisans uyarısı.** Bu paket MIT lisanslıdır, ancak **indirdiğiniz verilerin lisansı
39
+ > her portala ve veriyi yayımlayan kuruma aittir** (İBB Açık Veri Lisansı, İzmir BB Açık
40
+ > Veri Lisansı, CC BY 4.0, CC BY-NC ...). Paket size veriler üzerinde hiçbir hak
41
+ > vermez. Her veri setinin lisansını (`bilgi` komutu veya `Dataset.license_title`)
42
+ > okuyun, koşullarına uyun ve kaynak gösterin. Ticari olmayan (NC) lisanslara özellikle
43
+ > dikkat edin.
44
+
45
+ ## Kurulum
46
+
47
+ ```bash
48
+ pip install tr-acikveri # yalnızca standart kütüphane
49
+ pip install "tr-acikveri[pandas]" # + DataFrame dönüşümü
50
+ pip install "tr-acikveri[excel]" # + XLSX/XLS okuma (pandas + openpyxl)
51
+ pip install "tr-acikveri[geo]" # + GeoDataFrame (geopandas)
52
+ pip install "tr-acikveri[certifi]" # + Mozilla CA paketi (bkz. "TLS sertifikaları")
53
+ ```
54
+
55
+ ## Hızlı başlangıç (komut satırı)
56
+
57
+ ```bash
58
+ tr-acikveri portallar # CKAN portalları
59
+ tr-acikveri portallar --hepsi # CKAN olmayanlar dahil
60
+ tr-acikveri ara otopark -p ibb -p izmir -f csv -n 5
61
+ tr-acikveri bilgi ibb ispark-otopark-bilgileri
62
+ tr-acikveri indir konya otopark-bilgileri -f csv -o veri/
63
+ tr-acikveri kurumlar izmir --json
64
+ ```
65
+
66
+ Örnek çıktı (kısaltılmış, 2026-11-09):
67
+
68
+ ```
69
+ [konya] otopark-bilgileri
70
+ Otopark Bilgileri (CSV) · Destek Hizmetleri Dairesi Başkanlığı
71
+ [izmir] otopark-ucretleri
72
+ Otopark Ücretleri (CSV, XLSX) · İZELMAN A.Ş.
73
+
74
+ Toplam eşleşme 3 (izmir: 2; konya: 1); gösterilen 3.
75
+ ```
76
+
77
+ Ortak seçenekler: `--onbellek KLASÖR`, `--onbellek-suresi SN`, `--onbelleksiz`,
78
+ `--zaman-asimi SN`, `--aralik SN` (aynı sunucuya iki istek arası, varsayılan 1 sn),
79
+ `--yeniden-deneme N`, `--iletisim E-POSTA` (User-Agent'a eklenir), `--json`.
80
+ `-p` portal anahtarı, şehir adı (`İzmir`, `istanbul`) veya herhangi bir CKAN adresi
81
+ olabilir. Yönlendirilen çıktı (ör. `> sonuc.json`) her zaman UTF-8 yazılır.
82
+
83
+ ## Hızlı başlangıç (Python)
84
+
85
+ ```python
86
+ from tr_acikveri import AcikVeri
87
+
88
+ av = AcikVeri(contact="ad.soyad@kurum.edu.tr") # iletişim adresi önerilir
89
+
90
+ sonuc = av.search("otopark", portals=["ibb", "izmir", "konya"], formats=["csv"], rows=5)
91
+ for ds in sonuc:
92
+ print(ds.portal, ds.name, ds.formats, ds.license_title)
93
+ print(sonuc.counts, sonuc.errors)
94
+
95
+ ds = av.dataset("konya", "otopark-bilgileri")
96
+ kaynak = ds.resources_by_format(["csv"])[0]
97
+ tablo = av.read_csv(kaynak) # indirir (önbellek) ve okur
98
+ print(tablo.encoding, tablo.delimiter, tablo.columns)
99
+ kapasite = tablo.numeric("bolgekapasite") # "1.250" -> 1250.0
100
+
101
+ df = av.to_dataframe(kaynak, numeric=True) # [pandas]
102
+
103
+ parklar = av.search("park", portals=["trabzon"], formats=["geojson"]).datasets[0]
104
+ geo_kaynak = parklar.resources_by_format(["geojson"])[0]
105
+ geo = av.read_geojson(geo_kaynak) # FeatureCollection dict
106
+ gdf = av.to_geodataframe(geo_kaynak) # [geo]
107
+ ```
108
+
109
+ Tek portal için alt düzey istemci:
110
+
111
+ ```python
112
+ from tr_acikveri import CkanClient
113
+
114
+ ibb = CkanClient("ibb")
115
+ sayi, sayfa = ibb.search("bisiklet", formats=["geojson"], sort="metadata_modified desc")
116
+ for ds in ibb.iter_search("hava kalitesi", limit=200):
117
+ ...
118
+ kayitlar = ibb.datastore_search(resource_id, limit=100, filters={"ilce": "Kadıköy"})
119
+ ```
120
+
121
+ ## Portal kaydı
122
+
123
+ Her kayıt 2026-11-09 tarihinde `<adres>/api/3/action/status_show` adresine yapılan tek
124
+ bir salt okunur `GET` isteğiyle doğrulandı; lisans notları portalın `license_list`
125
+ ve `package_search` yanıtlarından alındı. Veri seti sayıları aynı tarihe aittir.
126
+
127
+ | Anahtar | Portal | Adres | Veri seti | Lisans (portalın bildirdiği) |
128
+ |---|---|---|---:|---|
129
+ | `ibb` | İstanbul BB | https://data.ibb.gov.tr | 565 | İBB Açık Veri Lisansı |
130
+ | `izmir` | İzmir BB | https://acikveri.bizizmir.com | 251 | İzmir BB Açık Veri Lisansı; bazıları CC BY / belirtilmemiş |
131
+ | `konya` | Konya BB | https://acikveri.konya.bel.tr | 233 | CC BY 4.0 |
132
+ | `gaziantep` | Gaziantep | https://acikveri.gaziantep.bel.tr | 252 | Gaziantep Açık Veri Lisansı |
133
+ | `balikesir` | Balıkesir BB | https://acikveri.balikesir.bel.tr | 252 | Balıkesir Açık Veri Lisansı |
134
+ | `denizli` | Denizli | https://acikveri.denizli.bel.tr | 39 | Denizli Açık Veri Lisansı |
135
+ | `trabzon` | Trabzon BB | https://acikveri.trabzon.bel.tr | 206 | Trabzon Açık Veri Lisansı |
136
+ | `manisa` | Manisa BB | https://acikveri.manisa.bel.tr | 1389 | Manisa BB Açık Veri Lisansı (mbb-odl-1.0) |
137
+ | `canakkale` | Çanakkale | https://acikveri.canakkale.bel.tr | 123 | Çanakkale Açık Veri Lisansı |
138
+ | `bursa-yesil` | Bursa Açık Yeşil | https://acikyesil.bursa.bel.tr | 49 | kurum lisansı (yalnızca yeşil alan verisi) |
139
+ | `kadikoy` | Kadıköy (ilçe) | https://acikveri.kadikoy.bel.tr | 161 | karışık: CC BY, CC BY-NC, CC BY-ND |
140
+ | `tuzla` | Tuzla (ilçe) | https://veri.tuzla.bel.tr | 91 | CC BY |
141
+ | `nilufer` | Nilüfer (ilçe) | https://acikveri.nilufer.bel.tr | 65 | çoğunda belirtilmemiş; bazıları CC BY / CC BY-NC |
142
+
143
+ Desteklenmeyen (CKAN API'si yok veya kontrol sırasında erişilemedi) ve
144
+ `portallar --hepsi` ile listelenenler: Ankara (seffaf.ankara.bel.tr), Kocaeli
145
+ (veri.kocaeli.bel.tr), Kayseri, Küçükçekmece, Sağlık Bakanlığı (özel yazılım);
146
+ Antalya, Sakarya ve ULASAV (ulasav.csb.gov.tr; erişilemedi, API türü doğrulanamadı).
147
+ Gaziantep, Denizli, Trabzon, Çanakkale, Balıkesir ve Bursa Açık Yeşil portalları
148
+ `ulasav-license` kimlikli ortak CKAN şablonunu kullanır; lisans metni her portalın
149
+ `/license` sayfasındadır.
150
+
151
+ Kayıtta olmayan bir CKAN portalı adresle kullanılabilir veya kaydedilebilir:
152
+
153
+ ```python
154
+ from tr_acikveri import Portal, register_portal, CkanClient
155
+
156
+ CkanClient("https://acikveri.ornek.bel.tr").search("imar")
157
+ register_portal(Portal("ornek", "Örnek Belediyesi", "https://acikveri.ornek.bel.tr",
158
+ city="Örnek", license_note="CC BY 4.0"))
159
+ ```
160
+
161
+ Portallar değişir: adres taşınabilir, API kapanabilir. Kayıttaki bilgiler kontrol
162
+ tarihindeki durumu yansıtır.
163
+
164
+ ## API özeti
165
+
166
+ | Nesne | Açıklama |
167
+ |---|---|
168
+ | `AcikVeri(portals=None, cache_dir=None, cache_ttl=86400, contact=None, timeout=30, min_interval=1.0, retries=3, max_workers=4)` | Çok portallı istemci |
169
+ | `.search(query, portals, formats, rows, organization, tags, sort)` → `SearchResult` | `datasets`, `counts`, `errors`, `total` |
170
+ | `.dataset(portal, ad)` → `Dataset`; `.resources(portal, ad, formats)` → `[Resource]` | Meta veri ve kaynaklar |
171
+ | `.organizations(portal)`, `.tags(portal, query)` | Kurumlar, etiketler |
172
+ | `.download(resource, dest=None, overwrite, resume, max_bytes, progress)` → `Path` | Önbelleğe veya hedefe indirme; `.meta.json` kaynak bilgisi |
173
+ | `.download_dataset(portal, ad, formats, dest_dir)` | Veri setinin tüm dosyaları |
174
+ | `.read_csv`, `.read_geojson`, `.load`, `.to_dataframe`, `.to_geodataframe` | Okuma |
175
+ | `CkanClient(portal)` | `search`, `iter_search`, `dataset`, `resource`, `organizations`, `tags`, `licenses`, `datastore_search`, `action` |
176
+ | `list_portals`, `get_portal`, `register_portal`, `Portal` | Portal kaydı |
177
+ | `read_csv`, `CsvTable`, `detect_encoding`, `sniff_delimiter`, `parse_number`, `read_geojson`, `geojson_crs` | Dosya okuyucular |
178
+ | `HttpClient`, `RetryPolicy`, `RateLimiter`, `Cache` | Taşıma katmanı |
179
+ | `AcikVeriError` → `HttpError`, `TransportError`, `CkanError` → `NotFoundError`, `UnsupportedPortalError`, `PortalNotFoundError`, `FormatError`, `MissingDependencyError` | Hatalar |
180
+
181
+ ## Yöntem ve kaynaklar
182
+
183
+ - **CKAN Action API v3** — yalnızca okuma eylemleri (`status_show`, `package_search`,
184
+ `package_show`, `resource_show`, `organization_list`, `tag_list`, `license_list`,
185
+ `datastore_search`), hepsi `GET` ile. Kaynak: CKAN API belgeleri,
186
+ https://docs.ckan.org/en/2.9/api/. `package_search` için `rows` en fazla 1000'e
187
+ sınırlanır (CKAN'ın `ckan.search.rows_max` varsayılanı).
188
+ - **Biçim filtresi** — `res_format` Solr'da birebir eşleşen bir alan olduğundan,
189
+ portallarda görülen yazımların tamamı (`CSV`, `csv`, `.csv`, `GeoJSON`, `.shp`,
190
+ `Excel` ...) sunucuya gönderilir; sonuç ayrıca istemci tarafında normalleştirilmiş
191
+ biçimle süzülür.
192
+ - **HTTP** — `Retry-After` (saniye veya HTTP tarihi) ve `Range`/`Content-Range`
193
+ ile sürdürme: RFC 9110 §10.2.3 ve §14. Yeniden deneme 408/425/429/5xx ve ağ
194
+ hatalarında, üstel bekleme (+%10 rastgele) ile yapılır. Hız sınırı sunucu (host)
195
+ başınadır ve iş parçacıkları arasında paylaşılır.
196
+ - **Kodlama** — sıra: UTF-8 BOM → UTF-16 BOM → katı UTF-8 → Windows-1254 (cp1254,
197
+ Türkçe Windows kod sayfası) → ISO-8859-9. Ayraç, ilk 50 satırda en tutarlı sütun
198
+ sayısını veren adaydır (`;`, `,`, sekme, `|`; eşitlikte `;`).
199
+ - **Sayılar** — `parse_number` Türkçe yazımı (ondalık virgül, binlik nokta) varsayar;
200
+ yalnızca nokta içeren ve binlik gruplamaya uymayan değerler (`12.5`) ondalık
201
+ okunur. `%`, `TL`, `₺` ve boşluklar yok sayılır.
202
+ - **GeoJSON** — RFC 7946 (WGS 84, `EPSG:4326`). 2008 GeoJSON belirtimindeki `crs`
203
+ alanı varsa (`urn:ogc:def:crs:EPSG::5254` gibi) `geojson_crs` bu kodu döndürür ve
204
+ `to_geodataframe` onu kullanır.
205
+
206
+ ## TLS sertifikaları
207
+
208
+ Sertifika doğrulaması her zaman açıktır. Bazı portallar (kontrol tarihinde
209
+ `data.ibb.gov.tr`) Windows'un yalnızca gerektiğinde indirdiği bir kök sertifikaya
210
+ zincirlenir; Python bu durumda `CERTIFICATE_VERIFY_FAILED` hatası verir.
211
+ `certifi` kuruluysa (`pip install "tr-acikveri[certifi]"`) paket otomatik olarak
212
+ Mozilla CA paketini kullanır. Alternatifler: `SSL_CERT_FILE` ortam değişkeni,
213
+ `HttpClient(ca_file=...)` veya `HttpClient(ssl_context=...)`.
214
+
215
+ ## Önbellek
216
+
217
+ Varsayılan klasör `TR_ACIKVERI_CACHE` ortam değişkeni, yoksa Windows'ta
218
+ `%LOCALAPPDATA%\tr-acikveri`, diğer sistemlerde `~/.cache/tr-acikveri`'dir.
219
+ API yanıtları `api/` altında (varsayılan 1 gün), indirilen dosyalar
220
+ `files/<portal>/<kaynak kimliği>/` altında tutulur. Her dosyanın yanında kaynak
221
+ adresi, portal, veri seti, indirme zamanı ve HTTP doğrulayıcılarını içeren bir
222
+ `.meta.json` bulunur. İndirilen verileri bir git deposuna eklemeyin.
223
+
224
+ ## Sınırlamalar
225
+
226
+ - Yalnızca CKAN portalları desteklenir; özel yazılımlı portallar (Ankara, Kocaeli,
227
+ Kayseri, Sağlık Bakanlığı ...) kayıtta yalnızca bilgi amaçlıdır.
228
+ - Portal listesi, veri seti sayıları ve lisans notları 2026-11-09 tarihli kontrollere
229
+ dayanır; değişebilir. Bağlayıcı olan, veri setinin portaldaki lisansıdır.
230
+ - Kodlama tespiti sezgiseldir: UTF-8 olarak geçerli olan cp1254 dosyaları (çok nadir)
231
+ UTF-8 sayılır; gerekirse `encoding="cp1254"` verin.
232
+ - `API`/`HTML` türündeki kaynaklar dosya değildir ve varsayılan olarak indirilmez.
233
+ - Çok portallı aramada `rows` portal başına uygulanır; sonuçlar portallar arasında
234
+ yeniden sıralanmaz.
235
+ - Önbellekteki dosya, sunucuda güncellense bile `overwrite=True` (CLI: `--yeniden`)
236
+ verilmedikçe yeniden indirilmez.
237
+
238
+ ## Geliştirme
239
+
240
+ ```bash
241
+ pip install -e ".[dev,pandas]"
242
+ pytest --cov=tr_acikveri
243
+ ruff check . && ruff format --check src tests && mypy src
244
+ ```
245
+
246
+ Testler gerçek ağa hiç çıkmaz: `tests/mockserver.py` iki CKAN portalını, hatalı
247
+ portalları (500, HTML), 429/503 yanıtlarını, bağlantısı yarıda kopan indirmeleri ve
248
+ `Range` desteği olmayan sunucuları taklit eden yerel bir HTTP sunucusudur.
249
+
250
+ ## Lisans
251
+
252
+ MIT © 2026 Yusuf Eminoğlu. Bkz. [LICENSE](LICENSE). Bu lisans yalnızca yazılımı
253
+ kapsar; portallardan alınan veriler kendi lisanslarına tabidir.
254
+
255
+ ## Academic citation
256
+
257
+ ```bibtex
258
+ @software{eminoglu_tr_acikveri,
259
+ author = {Eminoğlu, Yusuf},
260
+ title = {tr-acikveri},
261
+ year = {2026},
262
+ version = {0.1.0},
263
+ url = {https://github.com/YusufEminoglu/tr_acikveri_sdk}
264
+ }
265
+ ```
266
+
267
+ Ayrıca bkz. `CITATION.cff`.