Skip to content
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
8 changes: 5 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ jobs:
id: repo
uses: actions/checkout@v3

- name: Build PyPI Package
run: |
python3 setup.py test
- name: Add missing setuptools
run: brew install python-setuptools

- name: Run tests
run: python3 setup.py test
7 changes: 5 additions & 2 deletions deps/frameworks/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ FRAMEWORK_REPO = https://github.com/gregneagle/relocatable-python.git
BUILD_OPTS = --os-version=11 --python-version=$(PYTHON_VERSION) --upgrade-pip --pip-requirements=requirements.txt
BIN = ./Python.framework/Versions/Current/bin

# Use PIP_NO_CACHE_DIR from environment if set, otherwise empty
PIP_ENV = $(if $(PIP_NO_CACHE_DIR),PIP_NO_CACHE_DIR=1,)

all: Python.framework
$(BIN)/pip3 install --upgrade ../..
$(PIP_ENV) $(BIN)/pip3 install --upgrade ../..

Python.framework: relocatable-python
python3 ./relocatable-python/make_relocatable_python_framework.py $(BUILD_OPTS)
PYTHONNOUSERSITE=1 $(PIP_ENV) python3 ./relocatable-python/make_relocatable_python_framework.py $(BUILD_OPTS)
$(BIN)/python3 config.py ../../app/python.xcconfig

relocatable-python:
Expand Down
5 changes: 2 additions & 3 deletions deps/frameworks/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# --no-binary :all:
xattr
cachecontrol
cachecontrol[filecache]
cffi
lockfile
pyobjc
pyobjc==8.5
requests
six
29 changes: 21 additions & 8 deletions plotdevice/util/readers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

# files & io
from io import open, StringIO, BytesIO
from os.path import abspath, dirname, exists, join, splitext
from os.path import abspath, dirname, exists, join, splitext, expanduser
from plotdevice import DeviceError, INTERNAL

# data formats
Expand Down Expand Up @@ -190,13 +190,25 @@ def csv_dialect(fd):

### HTTP utils ###

import requests
from cachecontrol import CacheControl, CacheControlAdapter
from cachecontrol.caches import FileCache
from cachecontrol.heuristics import LastModified
HTTP = None

cache_dir = '%s/Library/Caches/PlotDevice'%os.environ['HOME']
HTTP = CacheControl(requests.Session(), cache=FileCache(cache_dir), heuristic=LastModified())
def get_http_session():
"""Returns a cached HTTP session (creating it if necessary)"""
global HTTP
if HTTP is None:
try:
from cachecontrol import CacheControl
from cachecontrol.caches import FileCache
from cachecontrol.heuristics import LastModified
import requests

cache_dir = join(expanduser('~'), 'Library/Caches/PlotDevice')
HTTP = CacheControl(requests.Session(),
cache=FileCache(cache_dir),
heuristic=LastModified())
except ImportError as e:
raise ImportError("HTTP dependencies not available. Install with: pip install requests cachecontrol[filecache]") from e
return HTTP

def binaryish(content, format):
bin_types = ('pdf','eps','png','jpg','jpeg','heic','gif','tiff','tif','zip','tar','gz')
Expand Down Expand Up @@ -244,7 +256,8 @@ def read(pth, format=None, encoding=None, cols=None, **kwargs):
"""

if re.match(r'https?:', pth):
resp = HTTP.get(pth)
session = get_http_session() # Get the session only when needed
resp = session.get(pth)
resp.raise_for_status()

extension_type = splitext(urlparse(pth).path)[-1]
Expand Down
88 changes: 61 additions & 27 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
"Intended Audience :: Developers",
"Intended Audience :: Education",
"Intended Audience :: End Users/Desktop",
"License :: OSI Approved :: MIT License",
"Operating System :: MacOS :: MacOS X",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
Expand Down Expand Up @@ -182,33 +181,63 @@ def stale(dst, src):
## Build Commands ##

class CleanCommand(Command):
description = "wipe out the ./build & ./dist dirs and other setup-generated files"
user_options = []
description = "wipe out generated files and build artifacts"
user_options = [
('dist', None, 'also remove Python.framework and local dependencies'),
]

def initialize_options(self):
pass
self.dist = None

def finalize_options(self):
pass

def run(self):
os.system('rm -rf ./build ./dist')
os.system('rm -rf plotdevice.egg-info MANIFEST.in PKG')
os.system('rm -rf ./tests/_out ./tests/_diff ./details.html')
os.system('rm -f ./_plotdevice.*.so')
os.system('cd deps/extensions/svg && make clean')
os.system('find plotdevice -name .DS_Store -exec rm {} \;')
os.system('find plotdevice -name \*.pyc -exec rm {} \;')
os.system('find plotdevice -name __pycache__ -type d -prune -exec rmdir {} \;')

class DistCleanCommand(Command):
paths = [
'build',
'dist',
'*.egg',
'*.egg-info',
'.eggs',
'MANIFEST.in',
'PKG',
'tests/_out',
'tests/_diff',
'details.html',
'_plotdevice.*.so',
'**/*.pyc',
'**/__pycache__',
'**/.DS_Store',
]

# Add framework paths if --dist flag is used
if self.dist:
paths.extend([
'deps/local',
'deps/frameworks/Python.framework',
'deps/frameworks/relocatable-python',
])

for path_pattern in paths:
for path in glob(path_pattern, recursive=True):
if exists(path):
print('removing %s'%path)
if os.path.isdir(path):
rmtree(path)
else:
os.unlink(path)

# Run make clean in svg extensions dir
if exists('deps/extensions/svg'):
os.system('cd deps/extensions/svg && make clean')

class DistCleanCommand(CleanCommand):
"""Alias for `clean --dist` for backward compatibility"""
description = "delete Python.framework, local pypi dependencies, and all generated files"
user_options = []

def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
self.run_command('clean')
os.system('rm -rf ./deps/local')
os.system('rm -rf ./deps/frameworks/*.framework')
super().initialize_options()
self.dist = True # always do a deep clean

class LocalDevCommand(Command):
description = "set up environment to allow for running `python -m plotdevice` within the repo"
Expand Down Expand Up @@ -308,14 +337,20 @@ def run(self):

class BuildAppCommand(Command):
description = "Build PlotDevice.app with xcode"
user_options = []
user_options = [
('no-cache', None, 'do not use pip cache when installing dependencies'),
]

def initialize_options(self):
pass
self.no_cache = None

def finalize_options(self):
# make sure the embedded framework exists (and has updated app/python.xcconfig)
print("Set up Python.framework for app build")
call('cd deps/frameworks && make', shell=True)
env = os.environ.copy()
if self.no_cache:
env['PIP_NO_CACHE_DIR'] = '1'
call('cd deps/frameworks && make', shell=True, env=env)

def run(self):
self.spawn(['xcodebuild', '-configuration', 'Release'])
Expand Down Expand Up @@ -470,8 +505,7 @@ def codesign(root, name=None, exec=False, entitlement=False):
)],
install_requires = [
'requests',
'cachecontrol',
'lockfile',
'cachecontrol[filecache]',
'pyobjc-core==8.5',
'pyobjc-framework-Quartz==8.5',
'pyobjc-framework-LaunchServices==8.5',
Expand Down