mac-alias 2.0.1__tar.gz → 2.0.4__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.
@@ -1,12 +1,25 @@
1
1
  Metadata-Version: 1.1
2
2
  Name: mac_alias
3
- Version: 2.0.1
3
+ Version: 2.0.4
4
4
  Summary: Generate/parse Mac OS Alias records from Python
5
5
  Home-page: http://alastairs-place.net/projects/mac_alias
6
6
  Author: Alastair Houghton
7
7
  Author-email: alastair@alastairs-place.net
8
8
  License: MIT License
9
- Description: ``mac_alias`` lets you generate or read binary Alias and Bookmark records
9
+ Description: =========
10
+ mac_alias
11
+ =========
12
+
13
+ .. image:: https://travis-ci.org/al45tair/mac_alias.svg?branch=master
14
+ :target: https://travis-ci.org/al45tair/mac_alias
15
+
16
+ .. image:: https://readthedocs.org/projects/mac_alias/badge/?version=latest
17
+ :target: http://mac_alias.readthedocs.io/en/latest/?badge=latest
18
+
19
+ What is this?
20
+ -------------
21
+
22
+ ``mac_alias`` lets you generate or read binary Alias and Bookmark records
10
23
  from Python code.
11
24
 
12
25
  While it is written in pure Python, some OS X specific code is required to
@@ -18,6 +31,10 @@ Description: ``mac_alias`` lets you generate or read binary Alias and Bookmark r
18
31
  <alastair@alastairs-place.net> was responsible for reverse engineering the
19
32
  bookmark format.
20
33
 
34
+ See the documentation_ for more information.
35
+
36
+ .. _documentation:: http://mac-alias.rtfd.org
37
+
21
38
  Platform: darwin
22
39
  Classifier: Development Status :: 5 - Production/Stable
23
40
  Classifier: License :: OSI Approved :: MIT License
@@ -1,3 +1,16 @@
1
+ =========
2
+ mac_alias
3
+ =========
4
+
5
+ .. image:: https://travis-ci.org/al45tair/mac_alias.svg?branch=master
6
+ :target: https://travis-ci.org/al45tair/mac_alias
7
+
8
+ .. image:: https://readthedocs.org/projects/mac_alias/badge/?version=latest
9
+ :target: http://mac_alias.readthedocs.io/en/latest/?badge=latest
10
+
11
+ What is this?
12
+ -------------
13
+
1
14
  ``mac_alias`` lets you generate or read binary Alias and Bookmark records
2
15
  from Python code.
3
16
 
@@ -9,3 +22,7 @@ Credit is due to Wim Lewis <wiml@hhhh.org>, whose work on reverse engineering
9
22
  the alias format was extremely useful in writing this code. Alastair Houghton
10
23
  <alastair@alastairs-place.net> was responsible for reverse engineering the
11
24
  bookmark format.
25
+
26
+ See the documentation_ for more information.
27
+
28
+ .. _documentation:: http://mac-alias.rtfd.org
@@ -14,6 +14,11 @@ import sys
14
14
  if sys.platform == 'darwin':
15
15
  from . import osx
16
16
 
17
+ try:
18
+ long
19
+ except NameError:
20
+ long = int
21
+
17
22
  from .utils import *
18
23
 
19
24
  ALIAS_KIND_FILE = 0
@@ -30,6 +35,16 @@ ALIAS_EJECTABLE_DISK = 5
30
35
 
31
36
  ALIAS_NO_CNID = 0xffffffff
32
37
 
38
+ def encode_utf8(s):
39
+ if isinstance(s, bytes):
40
+ return s
41
+ return s.encode('utf-8')
42
+
43
+ def decode_utf8(s):
44
+ if isinstance(s, bytes):
45
+ return s.decode('utf-8')
46
+ return s
47
+
33
48
  class AppleShareInfo (object):
34
49
  def __init__(self, zone=None, server=None, user=None):
35
50
  #: The AppleShare zone
@@ -323,6 +338,8 @@ class Alias (object):
323
338
  """Create an :class:`Alias` that points at the specified file."""
324
339
  if sys.platform != 'darwin':
325
340
  raise Exception('Not implemented (requires special support)')
341
+
342
+ path = encode_utf8(path)
326
343
 
327
344
  a = Alias()
328
345
 
@@ -337,7 +354,7 @@ class Alias (object):
337
354
  volinfo = osx.getattrlist(vol_path, attrs, 0)
338
355
 
339
356
  vol_crtime = volinfo[0]
340
- vol_name = volinfo[1]
357
+ vol_name = encode_utf8(volinfo[1])
341
358
 
342
359
  # Also grab various attributes of the file
343
360
  attrs = [(osx.ATTR_CMN_OBJTYPE
@@ -357,7 +374,7 @@ class Alias (object):
357
374
 
358
375
  dirname, filename = os.path.split(path)
359
376
 
360
- if dirname == '' or dirname == '.':
377
+ if dirname == b'' or dirname == b'.':
361
378
  dirname = os.getcwd()
362
379
 
363
380
  foldername = os.path.basename(dirname)
@@ -382,10 +399,10 @@ class Alias (object):
382
399
  rel_path = os.path.relpath(path, vol_path)
383
400
 
384
401
  # Leave off the initial '/' if vol_path is '/' (no idea why)
385
- if vol_path == '/':
402
+ if vol_path == b'/':
386
403
  a.target.posix_path = rel_path
387
404
  else:
388
- a.target.posix_path = '/' + rel_path
405
+ a.target.posix_path = b'/' + rel_path
389
406
 
390
407
  # Construct the Carbon and CNID paths
391
408
  carbon_path = []
@@ -398,10 +415,11 @@ class Alias (object):
398
415
  attrs = [osx.ATTR_CMN_FILEID, 0, 0, 0, 0]
399
416
  info = osx.getattrlist(os.path.join(vol_path, head), attrs, 0)
400
417
  cnid_path.append(info[0])
401
- carbon_tail = tail.replace(':','/')
418
+ carbon_tail = tail.replace(b':',b'/')
402
419
  carbon_path.insert(0, carbon_tail)
403
420
  head, tail = os.path.split(head)
404
- carbon_path = vol_name + ':' + ':\0'.join(carbon_path)
421
+
422
+ carbon_path = vol_name + b':' + b':\0'.join(carbon_path)
405
423
 
406
424
  a.target.carbon_path = carbon_path
407
425
  a.target.cnid_path = cnid_path
@@ -413,8 +431,8 @@ class Alias (object):
413
431
  pos = b.tell()
414
432
  b.write(struct.pack(b'>4shh', self.appinfo, 0, self.version))
415
433
 
416
- carbon_volname = self.volume.name.replace(':','/').encode('utf-8')
417
- carbon_filename = self.target.filename.replace(':','/').encode('utf-8')
434
+ carbon_volname = encode_utf8(self.volume.name).replace(b':',b'/')
435
+ carbon_filename = encode_utf8(self.target.filename).replace(b':',b'/')
418
436
  voldate = (self.volume.creation_date - mac_epoch).total_seconds()
419
437
  crdate = (self.target.creation_date - mac_epoch).total_seconds()
420
438
 
@@ -422,13 +440,13 @@ class Alias (object):
422
440
  # (so doing so is ridiculous, and nothing could rely on it).
423
441
  b.write(struct.pack(b'>h28pI2shI64pII4s4shhI2s10s',
424
442
  self.target.kind,
425
- carbon_volname, voldate,
443
+ carbon_volname, int(voldate),
426
444
  self.volume.fs_type,
427
445
  self.volume.disk_type,
428
446
  self.target.folder_cnid,
429
447
  carbon_filename,
430
448
  self.target.cnid,
431
- crdate,
449
+ int(crdate),
432
450
  self.target.creator_code,
433
451
  self.target.type_code,
434
452
  self.target.levels_from,
@@ -439,8 +457,8 @@ class Alias (object):
439
457
 
440
458
  # Excuse the odd order; we're copying Finder
441
459
  if self.target.folder_name:
442
- carbon_foldername = self.target.folder_name.replace(':','/')\
443
- .encode('utf-8')
460
+ carbon_foldername = encode_utf8(self.target.folder_name)\
461
+ .replace(b':',b'/')
444
462
  b.write(struct.pack(b'>hh', TAG_CARBON_FOLDER_NAME,
445
463
  len(carbon_foldername)))
446
464
  b.write(carbon_foldername)
@@ -461,7 +479,7 @@ class Alias (object):
461
479
  b.write(cnid_path)
462
480
 
463
481
  if self.target.carbon_path:
464
- carbon_path=self.target.carbon_path.encode('utf-8')
482
+ carbon_path=encode_utf8(self.target.carbon_path)
465
483
  b.write(struct.pack(b'>hh', TAG_CARBON_PATH,
466
484
  len(carbon_path)))
467
485
  b.write(carbon_path)
@@ -490,7 +508,7 @@ class Alias (object):
490
508
  b.write(b'\0')
491
509
 
492
510
  if self.volume.driver_name:
493
- driver_name = self.volume.driver_name.encode('utf-8')
511
+ driver_name = encode_utf8(self.volume.driver_name)
494
512
  b.write(struct.pack(b'>hh', TAG_DRIVER_NAME,
495
513
  len(driver_name)))
496
514
  b.write(driver_name)
@@ -511,20 +529,22 @@ class Alias (object):
511
529
  if len(self.volume.network_mount_info) & 1:
512
530
  b.write(b'\0')
513
531
 
514
- utf16 = self.target.filename.replace(':','/').encode('utf-16-be')
532
+ utf16 = decode_utf8(self.target.filename)\
533
+ .replace(':','/').encode('utf-16-be')
515
534
  b.write(struct.pack(b'>hhh', TAG_UNICODE_FILENAME,
516
535
  len(utf16) + 2,
517
536
  len(utf16) // 2))
518
537
  b.write(utf16)
519
538
 
520
- utf16 = self.volume.name.replace(':','/').encode('utf-16-be')
539
+ utf16 = decode_utf8(self.volume.name)\
540
+ .replace(':','/').encode('utf-16-be')
521
541
  b.write(struct.pack(b'>hhh', TAG_UNICODE_VOLUME_NAME,
522
542
  len(utf16) + 2,
523
543
  len(utf16) // 2))
524
544
  b.write(utf16)
525
545
 
526
546
  if self.target.posix_path:
527
- posix_path = self.target.posix_path.encode('utf-8')
547
+ posix_path = encode_utf8(self.target.posix_path)
528
548
  b.write(struct.pack(b'>hh', TAG_POSIX_PATH,
529
549
  len(posix_path)))
530
550
  b.write(posix_path)
@@ -532,7 +552,7 @@ class Alias (object):
532
552
  b.write(b'\0')
533
553
 
534
554
  if self.volume.posix_path:
535
- posix_path = self.volume.posix_path.encode('utf-8')
555
+ posix_path = encode_utf8(self.volume.posix_path)
536
556
  b.write(struct.pack(b'>hh', TAG_POSIX_PATH_TO_MOUNTPOINT,
537
557
  len(posix_path)))
538
558
  b.write(posix_path)
@@ -4,7 +4,7 @@
4
4
  # for the old-fashioned alias format. The details of this format were
5
5
  # reverse engineered; some things are still not entirely clear.
6
6
  #
7
- from __future__ import unicode_literals
7
+ from __future__ import unicode_literals, print_function
8
8
 
9
9
  import struct
10
10
  import uuid
@@ -13,11 +13,26 @@ import os
13
13
  import sys
14
14
  import pprint
15
15
 
16
- from urlparse import urljoin
16
+ try:
17
+ from urlparse import urljoin
18
+ except ImportError:
19
+ from urllib.parse import urljoin
17
20
 
18
21
  if sys.platform == 'darwin':
19
22
  from . import osx
20
23
 
24
+ def iteritems(x):
25
+ return x.iteritems()
26
+
27
+ try:
28
+ unicode
29
+ except NameError:
30
+ unicode = str
31
+ long = int
32
+ xrange = range
33
+ def iteritems(x):
34
+ return x.items()
35
+
21
36
  from .utils import *
22
37
 
23
38
  BMK_DATA_TYPE_MASK = 0xffffff00
@@ -292,7 +307,7 @@ class Bookmark (object):
292
307
  elif dtype == BMK_NULL:
293
308
  return None
294
309
 
295
- print 'Unknown data type %08x' % typecode
310
+ print('Unknown data type %08x' % typecode)
296
311
  return (typecode, databytes)
297
312
 
298
313
  @classmethod
@@ -304,8 +319,8 @@ class Bookmark (object):
304
319
 
305
320
  magic,size,dummy,hdrsize = struct.unpack(b'<4sIII', data[0:16])
306
321
 
307
- if magic != 'book':
308
- raise ValueError('Not a bookmark file (bad magic)')
322
+ if magic != b'book':
323
+ raise ValueError('Not a bookmark file (bad magic) %r' % magic)
309
324
 
310
325
  if hdrsize < 16:
311
326
  raise ValueError('Not a bookmark file (header size too short)')
@@ -442,7 +457,7 @@ class Bookmark (object):
442
457
  ioffset = offset + 8 + len(item) * 8
443
458
  result = [struct.pack(b'<II', len(item) * 8, BMK_DICT | BMK_ST_ONE)]
444
459
  enc = []
445
- for k,v in item.iteritems():
460
+ for k,v in iteritems(item):
446
461
  result.append(struct.pack(b'<I', ioffset))
447
462
  ioffset, ienc = cls._encode_item(k, ioffset)
448
463
  enc.append(ienc)
@@ -476,8 +491,8 @@ class Bookmark (object):
476
491
  for tid,toc in self.tocs:
477
492
  entries = []
478
493
 
479
- for k,v in toc.iteritems():
480
- if isinstance(k, basestring):
494
+ for k,v in iteritems(toc):
495
+ if isinstance(k, (str, unicode)):
481
496
  noffset = offset
482
497
  voffset, enc = self._encode_item(k, offset)
483
498
  result.append(enc)
@@ -510,7 +525,7 @@ class Bookmark (object):
510
525
  0xfffffffe,
511
526
  tid,
512
527
  next_offset,
513
- len(data) / 12))
528
+ len(data) // 12))
514
529
  result.append(data)
515
530
 
516
531
  offset += 20 + len(data)
@@ -533,7 +548,7 @@ class Bookmark (object):
533
548
 
534
549
  # Find the filesystem
535
550
  st = osx.statfs(path)
536
- vol_path = st.f_mntonname
551
+ vol_path = st.f_mntonname.decode('utf-8')
537
552
 
538
553
  # Grab its attributes
539
554
  attrs = [osx.ATTR_CMN_CRTIME,
@@ -580,6 +595,9 @@ class Bookmark (object):
580
595
 
581
596
  foldername = os.path.basename(dirname)
582
597
 
598
+ print(repr(path))
599
+ print(repr(vol_path))
600
+
583
601
  rel_path = os.path.relpath(path, vol_path)
584
602
 
585
603
  # Build the path arrays
@@ -606,6 +624,12 @@ class Bookmark (object):
606
624
  volprops = Data(struct.pack(b'<QQQ', 0x81 | kCFURLVolumeSupportsPersistentIDs,
607
625
  0x13ef | kCFURLVolumeSupportsPersistentIDs, 0))
608
626
 
627
+ print(repr(name_path))
628
+ print(repr(cnid_path))
629
+ print(repr(fileprops))
630
+ print(repr(vol_path))
631
+ print(repr(vol_name))
632
+
609
633
  toc = {
610
634
  kBookmarkPath: name_path,
611
635
  kBookmarkCNIDPath: cnid_path,
@@ -635,8 +659,8 @@ class Bookmark (object):
635
659
  result = ['Bookmark([']
636
660
  for tid,toc in self.tocs:
637
661
  result.append('(0x%x, {\n' % tid)
638
- for k,v in toc.iteritems():
639
- if isinstance(k, basestring):
662
+ for k,v in iteritems(toc):
663
+ if isinstance(k, (str, unicode)):
640
664
  kf = repr(k)
641
665
  else:
642
666
  kf = '0x%04x' % k
@@ -434,7 +434,7 @@ def _datetime_from_timespec(ts):
434
434
  return unix_epoch + td
435
435
 
436
436
  def _decode_utf8_nul(sz):
437
- nul = sz.find('\0')
437
+ nul = sz.find(b'\0')
438
438
  if nul > -1:
439
439
  sz = sz[:nul]
440
440
  return sz.decode('utf-8')
@@ -757,6 +757,8 @@ def _get_errno():
757
757
  return __error().contents.value
758
758
 
759
759
  def getattrlist(path, attrs, options):
760
+ if not isinstance(path, bytes):
761
+ path = path.encode('utf-8')
760
762
  attrs = list(attrs)
761
763
  if attrs[1]:
762
764
  attrs[1] |= ATTR_VOL_INFO
@@ -805,6 +807,8 @@ def fgetattrlist(fd, attrs, options):
805
807
  return _decode_attrlist_result(buf, attrs, options)
806
808
 
807
809
  def statfs(path):
810
+ if not isinstance(path, bytes):
811
+ path = path.encode('utf-8')
808
812
  result = struct_statfs()
809
813
  ret = _statfs(path, byref(result))
810
814
  if ret < 0:
@@ -1,12 +1,25 @@
1
1
  Metadata-Version: 1.1
2
2
  Name: mac-alias
3
- Version: 2.0.1
3
+ Version: 2.0.4
4
4
  Summary: Generate/parse Mac OS Alias records from Python
5
5
  Home-page: http://alastairs-place.net/projects/mac_alias
6
6
  Author: Alastair Houghton
7
7
  Author-email: alastair@alastairs-place.net
8
8
  License: MIT License
9
- Description: ``mac_alias`` lets you generate or read binary Alias and Bookmark records
9
+ Description: =========
10
+ mac_alias
11
+ =========
12
+
13
+ .. image:: https://travis-ci.org/al45tair/mac_alias.svg?branch=master
14
+ :target: https://travis-ci.org/al45tair/mac_alias
15
+
16
+ .. image:: https://readthedocs.org/projects/mac_alias/badge/?version=latest
17
+ :target: http://mac_alias.readthedocs.io/en/latest/?badge=latest
18
+
19
+ What is this?
20
+ -------------
21
+
22
+ ``mac_alias`` lets you generate or read binary Alias and Bookmark records
10
23
  from Python code.
11
24
 
12
25
  While it is written in pure Python, some OS X specific code is required to
@@ -18,6 +31,10 @@ Description: ``mac_alias`` lets you generate or read binary Alias and Bookmark r
18
31
  <alastair@alastairs-place.net> was responsible for reverse engineering the
19
32
  bookmark format.
20
33
 
34
+ See the documentation_ for more information.
35
+
36
+ .. _documentation:: http://mac-alias.rtfd.org
37
+
21
38
  Platform: darwin
22
39
  Classifier: Development Status :: 5 - Production/Stable
23
40
  Classifier: License :: OSI Approved :: MIT License
@@ -1,11 +1,25 @@
1
1
  # -*- coding: utf-8 -*-
2
+ import sys
2
3
  from setuptools import setup
3
4
 
4
- with open('README.rst', 'r') as f:
5
+ from setuptools.command.test import test as TestCommand
6
+
7
+ class PyTest(TestCommand):
8
+ def finalize_options(self):
9
+ TestCommand.finalize_options(self)
10
+ self.test_args = []
11
+ self.test_suite = True
12
+
13
+ def run_tests(self):
14
+ import pytest
15
+ errno = pytest.main(self.test_args)
16
+ sys.exit(errno)
17
+
18
+ with open('README.rst', 'rb') as f:
5
19
  longdesc = f.read().decode('utf-8')
6
20
 
7
21
  setup(name='mac_alias',
8
- version='2.0.1',
22
+ version='2.0.4',
9
23
  description='Generate/parse Mac OS Alias records from Python',
10
24
  long_description=longdesc,
11
25
  author='Alastair Houghton',
@@ -19,4 +33,8 @@ setup(name='mac_alias',
19
33
  'License :: OSI Approved :: MIT License',
20
34
  'Topic :: Desktop Environment',
21
35
  'Topic :: Software Development :: Libraries :: Python Modules'],
36
+ tests_require=['pytest'],
37
+ cmdclass={
38
+ 'test': PyTest
39
+ },
22
40
  provides=['mac_alias'])
File without changes
File without changes