tradedangerous 11.1.1__py3-none-any.whl → 11.1.3__py3-none-any.whl

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.

Potentially problematic release.


This version of tradedangerous might be problematic. Click here for more details.

@@ -3,42 +3,53 @@ Import plugin that uses data files from
3
3
  https://elite.tromador.com/ to update the Database.
4
4
  """
5
5
  from __future__ import annotations
6
+
7
+ from pathlib import Path
8
+ from .. import plugins, cache, transfers
9
+ from ..misc import progress as pbar
10
+ from ..plugins import PluginException
11
+
6
12
  import certifi
7
13
  import csv
8
14
  import datetime
9
- import json
10
15
  import os
16
+ import requests
11
17
  import sqlite3
12
18
  import ssl
13
- import time
14
19
  import typing
15
-
16
- from urllib import request
17
- from pathlib import Path
18
-
19
- from .. import plugins, cache, transfers
20
- from ..misc import progress as pbar
21
- from ..plugins import PluginException
20
+ import locale
21
+ import platform
22
22
 
23
23
 
24
24
  if typing.TYPE_CHECKING:
25
25
  from typing import Optional
26
26
  from .. tradeenv import TradeEnv
27
27
 
28
-
28
+ # Find the first English UTF-8 locale for use in parsing timestamps.
29
+ LOCALE = None
30
+ if platform.system() == 'Windows':
31
+ for lang in locale.windows_locale.values():
32
+ if "en" in lang:
33
+ LOCALE = lang
34
+ break
35
+ else:
36
+ # for other operating systems
37
+ for lang in locale.locale_alias.values():
38
+ if "en" in lang and "UTF-8" in lang:
39
+ LOCALE = lang
40
+ break
41
+ if not LOCALE:
42
+ raise PluginException(
43
+ "Unable to find compatible locale.\n" +
44
+ "This plugin needs an English, UTF-8 compatible " +
45
+ "locale installed in order to function correctly.\n" +
46
+ "Please refer to your OS for instructions installing one."
47
+ )
29
48
  # Constants
30
49
  BASE_URL = os.environ.get('TD_SERVER') or "https://elite.tromador.com/files/"
31
50
  CONTEXT=ssl.create_default_context(cafile=certifi.where())
32
51
 
33
52
 
34
- def _request_url(url, headers=None):
35
- data = None
36
- if headers:
37
- data = bytes(json.dumps(headers), encoding="utf-8")
38
-
39
- return request.urlopen(request.Request(url, data=data), context=CONTEXT, timeout=90)
40
-
41
-
42
53
  class DecodingError(PluginException):
43
54
  pass
44
55
 
@@ -159,10 +170,6 @@ class ImportPlugin(plugins.ImportPluginBase):
159
170
  """
160
171
  Fetch the latest dumpfile from the website if newer than local copy.
161
172
  """
162
-
163
- def openURL(url):
164
- return _request_url(url, headers = {'User-Agent': 'Trade-Dangerous'})
165
-
166
173
  if path not in (self.liveListingsPath, self.listingsPath):
167
174
  localPath = Path(self.tdb.dataPath, path)
168
175
  else:
@@ -171,24 +178,38 @@ class ImportPlugin(plugins.ImportPluginBase):
171
178
  url = BASE_URL + str(path)
172
179
 
173
180
  self.tdenv.NOTE("Checking for update to '{}'.", path)
181
+ # Use an HTTP Request header to obtain the Last-Modified and Content-Length headers.
182
+ # Also, tell the server to give us the un-compressed length of the file by saying
183
+ # that >this< request only wants text.
184
+ headers = {"User-Agent": "Trade-Dangerous", "Accept-Encoding": "text"}
174
185
  try:
175
- response = openURL(url)
186
+ response = requests.head(url, headers=headers, timeout=70)
176
187
  except Exception as e: # pylint: disable=broad-exception-caught
177
- self.tdenv.WARN("Problem with download:\n URL: {}\n Error: {}", BASE_URL + str(path), str(e))
188
+ self.tdenv.WARN("Problem with download:\n URL: {}\n Error: {}", url, str(e))
178
189
  return False
179
190
 
180
- url_time = response.getheader("Last-Modified")
181
- dumpModded = datetime.datetime.strptime(url_time, "%a, %d %b %Y %H:%M:%S %Z").timestamp()
191
+ locale.setlocale(locale.LC_ALL, LOCALE)
192
+ last_modified = response.headers.get("last-modified")
193
+ dump_mod_time = datetime.datetime.strptime(last_modified, "%a, %d %b %Y %H:%M:%S %Z").timestamp()
194
+ locale.setlocale(locale.LC_ALL, '')
182
195
 
183
196
  if Path.exists(localPath):
184
- localModded = localPath.stat().st_mtime
185
- if localModded >= dumpModded:
197
+ local_mod_time = localPath.stat().st_mtime
198
+ if local_mod_time >= dump_mod_time:
186
199
  self.tdenv.DEBUG0("'{}': Dump is not more recent than Local.", path)
187
200
  return False
188
201
 
202
+ # The server doesn't know the gzip'd length, and we won't see the gzip'd data,
203
+ # so we want the actual text-only length. Capture it here so we can tell the
204
+ # transfer mechanism how big the file is going to be.
205
+ length = response.headers.get("content-length")
206
+
189
207
  self.tdenv.NOTE("Downloading file '{}'.", path)
190
- transfers.download(self.tdenv, url, localPath)
191
- os.utime(localPath, (dumpModded, dumpModded))
208
+ transfers.download(self.tdenv, url, localPath, chunkSize=16384, length=length)
209
+
210
+ # Change the timestamps on the file so they match the website
211
+ os.utime(localPath, (dump_mod_time, dump_mod_time))
212
+
192
213
  return True
193
214
 
194
215
  def purgeSystems(self):
@@ -331,6 +352,10 @@ class ImportPlugin(plugins.ImportPluginBase):
331
352
  self.tdenv.NOTE("Finished processing market data. End time = {}", self.now())
332
353
 
333
354
  def run(self):
355
+ self.tdenv.DEBUG2(f'Using "{LOCALE}" locale for parsing modified timestamps. Please include this information in any error reports.')
356
+
357
+ self.tdenv.ignoreUnknown = True
358
+
334
359
  # Create the /eddb folder for downloading the source files if it doesn't exist.
335
360
  try:
336
361
  Path(str(self.dataPath)).mkdir()
@@ -487,8 +512,6 @@ class ImportPlugin(plugins.ImportPluginBase):
487
512
  self.tdb.close()
488
513
  self.tdb.reloadCache()
489
514
 
490
- self.tdenv.ignoreUnknown = True
491
-
492
515
  if self.getOption("purge"):
493
516
  self.purgeSystems()
494
517
 
tradedangerous/tradedb.py CHANGED
@@ -1150,8 +1150,9 @@ class TradeDB:
1150
1150
  self.tradingStationCount = 0
1151
1151
  # Fleet Carriers are station type 24.
1152
1152
  # Odyssey settlements are station type 25.
1153
+ # Assume type 0 (Unknown) are also Fleet Carriers.
1153
1154
  # Storing as a list allows easy expansion if needed.
1154
- types = {'fleet-carrier':[24,],'odyssey':[25,],}
1155
+ types = {'fleet-carrier':[24, 0,],'odyssey':[25,],}
1155
1156
  with closing(self.query(stmt)) as cur:
1156
1157
  for (
1157
1158
  ID, systemID, name,
@@ -1,6 +1,4 @@
1
- import csv
2
- import json
3
- import time
1
+ from __future__ import annotations
4
2
 
5
3
  from collections import deque
6
4
  from pathlib import Path
@@ -8,9 +6,20 @@ from .tradeexcept import TradeException
8
6
  from .misc import progress as pbar
9
7
  from . import fs
10
8
 
9
+ import csv
10
+ import json
11
+ import time
12
+ import typing
13
+
11
14
  import requests
12
15
 
13
16
 
17
+ if typing.TYPE_CHECKING:
18
+ import os # for PathLike
19
+ from .tradeenv import TradeEnv
20
+ from typing import Optional, Union
21
+
22
+
14
23
  ######################################################################
15
24
  # Helpers
16
25
 
@@ -31,12 +40,16 @@ def makeUnit(value):
31
40
  return None
32
41
 
33
42
  def download(
34
- tdenv, url, localFile,
35
- headers=None,
36
- backup=False,
37
- shebang=None,
38
- chunkSize=4096,
39
- timeout=90,
43
+ tdenv: TradeEnv,
44
+ url: str,
45
+ localFile: os.PathLike,
46
+ headers: Optional[dict] = None,
47
+ backup: bool = False,
48
+ shebang: Optional[str] = None,
49
+ chunkSize: int = 4096,
50
+ timeout: int = 90,
51
+ *,
52
+ length: Optional[Union[int, str]] = None,
40
53
  ):
41
54
  """
42
55
  Fetch data from a URL and save the output
@@ -57,21 +70,24 @@ def download(
57
70
  shebang:
58
71
  function to call on the first line
59
72
  """
60
-
61
73
  tdenv.NOTE("Requesting {}".format(url))
74
+
75
+ if isinstance(length, str):
76
+ length = int(length)
77
+
62
78
  req = requests.get(url, headers=headers or None, stream=True, timeout=timeout)
63
79
  req.raise_for_status()
64
80
 
65
81
  encoding = req.headers.get('content-encoding', 'uncompress')
66
- length = req.headers.get('content-length', None)
82
+ content_length = req.headers.get('content-length', length)
67
83
  transfer = req.headers.get('transfer-encoding', None)
68
- if transfer != 'chunked':
84
+ if not length and transfer != 'chunked':
69
85
  # chunked transfer-encoding doesn't need a content-length
70
- if length is None:
86
+ if content_length is None:
71
87
  print(req.headers)
72
88
  raise Exception("Remote server replied with invalid content-length.")
73
- length = int(length)
74
- if length <= 0:
89
+ content_length = int(content_length)
90
+ if content_length <= 0:
75
91
  raise TradeException(
76
92
  "Remote server gave an empty response. Please try again later."
77
93
  )
@@ -81,8 +97,8 @@ def download(
81
97
  # the uncompressed data, which should be larger, which will cause our
82
98
  # download indicators to sit at 100% for a really long time if the file is
83
99
  # heavily compressed and large (e.g spansh 1.5gb compressed vs 9GB uncompressed)
84
- if encoding == "gzip" and length:
85
- length *= 4
100
+ if length is None and encoding == "gzip" and content_length:
101
+ length = content_length * 3
86
102
 
87
103
  if tdenv.detail > 1:
88
104
  if length:
tradedangerous/version.py CHANGED
@@ -12,5 +12,5 @@
12
12
  """just keeper of current version"""
13
13
 
14
14
  # TODO: remember to update tests when version changes
15
- __version__ = '11.1.1'
15
+ __version__ = '11.1.3'
16
16
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tradedangerous
3
- Version: 11.1.1
3
+ Version: 11.1.3
4
4
  Summary: Trade-Dangerous is a set of powerful trading tools for Elite Dangerous, organized around one of the most powerful trade run optimizers available.
5
5
  Home-page: https://github.com/eyeonus/Trade-Dangerous
6
6
  Author: eyeonus
@@ -16,12 +16,12 @@ tradedangerous/prices.py,sha256=JqiDVrtvvPd5pqE3HdwOHOuFgdAbOR-pt0GLD3ZIXM8,7425
16
16
  tradedangerous/submit-distances.py,sha256=zxHtRpX10soJKLuRcun9uelfXGq2S9jvIWxD--P9zus,11709
17
17
  tradedangerous/tools.py,sha256=pp-4WtA12SVaaQHFJFOMTF7EDFRCU2mQeOhC4xoXmEk,1331
18
18
  tradedangerous/tradecalc.py,sha256=A7peEMiaCjlwFvReSq3E7_Ar0shUoFedQi83ZmOc7uY,42075
19
- tradedangerous/tradedb.py,sha256=3nGB55dYs4igP3U3J4Ye1-M6Kt9A4xPAMmnX7JEDW7w,72220
19
+ tradedangerous/tradedb.py,sha256=mitKkS4MczivDK_K7A-IC94hkObUmGWFhwIrh_ts9qw,72282
20
20
  tradedangerous/tradeenv.py,sha256=SDzRC6ERYZzzb_I6uexmFpFJJrnbzXa-1ogYt_GH26w,10576
21
21
  tradedangerous/tradeexcept.py,sha256=aZ-Y31MbkjF7lmAzBAbaMsPPE7FEEfuf4gaX2GvriDk,368
22
- tradedangerous/transfers.py,sha256=88gIvXpjd8T6NLxBrBRzmH2IfUmDDtiMcDTrc7qF3OI,7830
22
+ tradedangerous/transfers.py,sha256=KwskYBB5_TYDXx5fkN1ABYsPuPnICKdkEx0WUfC7BnA,8378
23
23
  tradedangerous/utils.py,sha256=PUPvAEqUyxYGqqQa0b_yfLAvq8YVUxK6HfdS-CxM-Lo,5186
24
- tradedangerous/version.py,sha256=Wg12sPeOttYgzGmg_sdMuARMhxxE3HUGUU49FBbne4E,646
24
+ tradedangerous/version.py,sha256=ghxPDFkK4akB_kG7EbpxFhrsQPs8VjNqdIUWHOPecuc,646
25
25
  tradedangerous/commands/TEMPLATE.py,sha256=MOE69xsZPHPIMBQ-LXicfsOlCZdy-2gPX_nlnwYYil8,2026
26
26
  tradedangerous/commands/__init__.py,sha256=3gz2cnXNZNkV1gtZh0dOnCRxBkQHbeIyysRe3bM2WEE,9516
27
27
  tradedangerous/commands/buildcache_cmd.py,sha256=jhNSqHX_xX43SiSUMFiKtWpB9v4oeZ0sqfNq6DCrjUs,2181
@@ -62,7 +62,7 @@ tradedangerous/misc/progress.py,sha256=NKvKP1OSCTpItc1CNxDuEH2A1oGJ6aWSyCdPSAjsG
62
62
  tradedangerous/plugins/__init__.py,sha256=TL-OIptlqNENKhoFqkFeBJn_vSw8L0pVaDJgjhaTj7A,7860
63
63
  tradedangerous/plugins/edapi_plug.py,sha256=5nqBYmjUceAt-KTfiBn7IEl443R1SsGLDmfVXgbcyms,42262
64
64
  tradedangerous/plugins/edcd_plug.py,sha256=JuDtuEM_mN9Sz2H09-qYizM-9N3cuNjgvQy7Y-wHwKw,14412
65
- tradedangerous/plugins/eddblink_plug.py,sha256=m1fSG9YQZZcJZhGzEk4y_OyAMK-psczZ-WxJ5JwxSbA,21525
65
+ tradedangerous/plugins/eddblink_plug.py,sha256=xK5snHevw8BIFfpYNtrJYRQekDD0DYkp62kcxSrkZ-8,22883
66
66
  tradedangerous/plugins/edmc_batch_plug.py,sha256=rrP_lFFxWsba8DPEo0WF2EdCiMoRC7tCT8z62MIvtIo,4173
67
67
  tradedangerous/plugins/journal_plug.py,sha256=5HMyoxQ7z42qj7NiL8rDxSyTN9gKikoQjyWzJLD-SYQ,23746
68
68
  tradedangerous/plugins/netlog_plug.py,sha256=yUl47l9xt3kGj9oSiY_FZaDGdnQj63oa9MBtSeIy1Zo,13469
@@ -71,9 +71,9 @@ tradedangerous/templates/Added.csv,sha256=8o54civQCcS9y7_DBo0GX196XWRbbREQqKDYTK
71
71
  tradedangerous/templates/Category.csv,sha256=8xwUDcBZE25T6x6dZGlRUMTCqeDLt3a9LXU5h6hRHV8,250
72
72
  tradedangerous/templates/RareItem.csv,sha256=F1RhRnTD82PiwrVUO-ai2ErGH2PTqNnQaDw5mcgljXs,10483
73
73
  tradedangerous/templates/TradeDangerous.sql,sha256=VlQK7QGtEi2brGtWaIZDvKmbJ_vLocD4CJ8h_6kKptU,7808
74
- tradedangerous-11.1.1.dist-info/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
75
- tradedangerous-11.1.1.dist-info/METADATA,sha256=VEWP-0GaU1u3FV8L1Oxx3IhBXGK5lAT1p8MEtr814LU,4435
76
- tradedangerous-11.1.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
77
- tradedangerous-11.1.1.dist-info/entry_points.txt,sha256=lrA7U9JHOcNuam2WEK4Hmc3vQ3mrJfsbJCE74qd9au8,62
78
- tradedangerous-11.1.1.dist-info/top_level.txt,sha256=JEoOVAhg5GfXZ4kHpNontu0RVzek_7P9_jp93f3Pqn8,16
79
- tradedangerous-11.1.1.dist-info/RECORD,,
74
+ tradedangerous-11.1.3.dist-info/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
75
+ tradedangerous-11.1.3.dist-info/METADATA,sha256=_YJd9yECrUzNkslTW4-PSLUoJPuS_EJIV3Dkxdymyq0,4435
76
+ tradedangerous-11.1.3.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
77
+ tradedangerous-11.1.3.dist-info/entry_points.txt,sha256=lrA7U9JHOcNuam2WEK4Hmc3vQ3mrJfsbJCE74qd9au8,62
78
+ tradedangerous-11.1.3.dist-info/top_level.txt,sha256=JEoOVAhg5GfXZ4kHpNontu0RVzek_7P9_jp93f3Pqn8,16
79
+ tradedangerous-11.1.3.dist-info/RECORD,,