| @ -0,0 +1,12 @@ | |||||
| *.py[co] | |||||
| *.log | |||||
| build | |||||
| dist | |||||
| docs/_* | |||||
| .env | |||||
| *.egg-info | |||||
| *.egg | |||||
| htmlcov | |||||
| .coverage | |||||
| models | |||||
| *.json | |||||
| @ -0,0 +1,4 @@ | |||||
| include README.* setup.py setup.cfg swuploader.py | |||||
| include bin * | |||||
| global-exclude *.pyc | |||||
| global-exclude *.pyo | |||||
| @ -0,0 +1,121 @@ | |||||
| Shapeways Uploader | |||||
| ================== | |||||
| Shapeways API bulk uploader. | |||||
| ## Install | |||||
| ### pip | |||||
| ```bash | |||||
| pip install swuploader | |||||
| ``` | |||||
| ### Git | |||||
| ```bash | |||||
| git clone git://github.com/brettlangdon/swuploader.git | |||||
| cd ./swuploader | |||||
| python setup.py install | |||||
| ``` | |||||
| ## Usage | |||||
| ``` | |||||
| Usage: | |||||
| swuploader (-h | --help) | |||||
| swuploader (-v | --version) | |||||
| swuploader auth [--server=<server>] <consumer_key> <consumer_secret> <output> | |||||
| swuploader upload [--models=<models>] [--out=<out>] [--server=<server>] <auth_tokens> | |||||
| Options: | |||||
| -h --help Show this help text | |||||
| -v --version Show version information | |||||
| -m <models> --models=<models> Set the directory for where model ini's are available [default: ./] | |||||
| -o <out> --out=<out> Set the directory where the model ini's are moved to after upload [default: ./] | |||||
| -s <server> --server=<server> Set different api server url if desired. | |||||
| ``` | |||||
| ### Setup App | |||||
| Before you can use `swuploader` you must have an application setup on | |||||
| shapeways.com this can be setup/registered at | |||||
| https://developers.shapeways.com/manage-apps/create. | |||||
| You will also need to note your `consumer key` and `consumer secret` from your | |||||
| app's settings page. | |||||
| ### Authenticate | |||||
| Once you have an application setup with shapeways.com you must authenticate with | |||||
| the api server before you can start to upload models, to do so run the | |||||
| following: | |||||
| ```bash | |||||
| swuploader auth <consumer_key> <consumer_secret> ./auth.json | |||||
| ``` | |||||
| This will give you a url to use for authentication, once you follow that url and | |||||
| authorize with your application you will be given a `verifier code` to enter to | |||||
| complete the authentication process. | |||||
| As a result of running this command you will have a file `auth.json` which will | |||||
| contain required keys/tokens/secrets necessary for all subsequent requests. | |||||
| ### Upload | |||||
| Finally you are ready to upload. In order to upload you need a folder which | |||||
| contains the model files that you want to upload (see | |||||
| http://www.shapeways.com/tutorials/supported-applications for a list of | |||||
| supported file types). | |||||
| For each model file you must supply an additional `.ini` file containing | |||||
| information about the model which is being uploaded. For example: | |||||
| ```ini | |||||
| name=Sphere | |||||
| file=./sphere.stl | |||||
| ``` | |||||
| For supported properties please see: | |||||
| http://developers.shapeways.com/docs?li=dh_docs#POST_-models-v1 for the list of | |||||
| accepted paramaters. | |||||
| *note* for materials, please provide them in the format | |||||
| `material.<material_id>=<markup>`. | |||||
| Your directory structure should look similar to: | |||||
| ```bash | |||||
| $ ls -1 | |||||
| auth.json | |||||
| model.obj | |||||
| model.ini | |||||
| sphere.ini | |||||
| sphere.stl | |||||
| ``` | |||||
| Once you have your model files and `.ini` files ready you can run `swuploader` | |||||
| like so: | |||||
| ```bash | |||||
| swuploader upload ./auth.json | |||||
| ``` | |||||
| `swuploader` will then read all the `.ini` files in the current directory and | |||||
| upload the model file assigned to the `file` attribute along with the other | |||||
| provided properties in the `.ini` file. | |||||
| ## License | |||||
| ``` | |||||
| The MIT License (MIT) Copyright (c) 2014 Brett Langdon <brett@blangdon.com> | |||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | |||||
| of this software and associated documentation files (the "Software"), to deal | |||||
| in the Software without restriction, including without limitation the rights to | |||||
| use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | |||||
| of the Software, and to permit persons to whom the Software is furnished to do | |||||
| so, subject to the following conditions: | |||||
| The above copyright notice and this permission notice shall be included in all | |||||
| copies or substantial portions of the Software. | |||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, | |||||
| INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | |||||
| PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |||||
| HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF | |||||
| CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE | |||||
| OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||||
| ``` | |||||
| @ -0,0 +1,63 @@ | |||||
| #!/usr/bin/env python | |||||
| import json | |||||
| import shutil | |||||
| import os | |||||
| import urlparse | |||||
| from shapeways.client import Client | |||||
| import swuploader | |||||
| import docopt | |||||
| __doc__ = """ | |||||
| Usage: | |||||
| swuploader (-h | --help) | |||||
| swuploader (-v | --version) | |||||
| swuploader auth [--server=<server>] <consumer_key> <consumer_secret> <output> | |||||
| swuploader upload [--models=<models>] [--out=<out>] [--server=<server>] <auth_tokens> | |||||
| Options: | |||||
| -h --help Show this help text | |||||
| -v --version Show version information | |||||
| -m <models> --models=<models> Set the directory for where model ini's are available [default: ./] | |||||
| -o <out> --out=<out> Set the directory where the model ini's are moved to after upload [default: ./] | |||||
| -s <server> --server=<server> Set different api server url if desired. | |||||
| """ | |||||
| args = docopt.docopt(__doc__, version="swuploader %s" % (swuploader.__version__, )) | |||||
| if args["auth"]: | |||||
| client = Client(args["<consumer_key>"], args["<consumer_secret>"]) | |||||
| if args["--server"]: | |||||
| client.base_url = args["--server"] | |||||
| url = client.connect() | |||||
| parts = urlparse.urlparse(url) | |||||
| qs = urlparse.parse_qs(parts.query) | |||||
| oauth_token = qs["oauth_token"][0] | |||||
| print "Please Visit: %s" % (url, ) | |||||
| verifier = raw_input("Paste Verifier Code: ") | |||||
| client.verify(oauth_token, verifier) | |||||
| auth_tokens = { | |||||
| "consumer_key": client.consumer_key, | |||||
| "consumer_secret": client.consumer_secret, | |||||
| "oauth_token": client.oauth_token, | |||||
| "oauth_secret": client.oauth_secret, | |||||
| } | |||||
| with open(args["<output>"], "w") as fp: | |||||
| json.dump(auth_tokens, fp) | |||||
| elif args["upload"]: | |||||
| auth_tokens = {} | |||||
| with open(args["<auth_tokens>"]) as fp: | |||||
| auth_tokens = json.load(fp) | |||||
| client = Client(**auth_tokens) | |||||
| if args["--server"]: | |||||
| client.base_url = args["--server"] | |||||
| for settings_filename, model in swuploader.get_models(args["--models"]): | |||||
| print "Uploading Model From: %s" % (settings_filename, ) | |||||
| results = swuploader.upload_model(model, client) | |||||
| if results: | |||||
| print "Visit Model At: %s" % (results["urls"]["editModelUrl"]["address"], ) | |||||
| basename = os.path.basename(settings_filename) | |||||
| new_location = os.path.abspath(os.path.join(args["--out"], basename)) | |||||
| shutil.move(settings_filename, new_location) | |||||
| else: | |||||
| print "Model Upload Failed" | |||||
| @ -0,0 +1,2 @@ | |||||
| shapeways==1.0.0 | |||||
| docopt==0.6.2 | |||||
| @ -0,0 +1,22 @@ | |||||
| #!/usr/bin/env python | |||||
| from setuptools import setup, find_packages | |||||
| from swuploader import __version__ | |||||
| setup( | |||||
| name='swuploader', | |||||
| version=__version__, | |||||
| author='Brett Langdon', | |||||
| author_email='brett@blangdon.com', | |||||
| packages=find_packages(), | |||||
| install_requires=[ | |||||
| 'shapeways==1.0.0', | |||||
| ], | |||||
| scripts=[ | |||||
| './bin/swuploader', | |||||
| ], | |||||
| setup_requires=[], | |||||
| description='Easy to up model uploader for Shapeways.com', | |||||
| url='http://github.com/brettlangdon/swuploader', | |||||
| ) | |||||
| @ -0,0 +1,61 @@ | |||||
| import base64 | |||||
| import glob | |||||
| import os | |||||
| __version__ = "0.1.0" | |||||
| def parse_settings(settings_filename): | |||||
| settings_filename = os.path.abspath(settings_filename) | |||||
| name, ext = os.path.splitext(os.path.basename(settings_filename)) | |||||
| settings = { | |||||
| "name": name, | |||||
| "hasRightsToModel": True, | |||||
| "acceptTermsAndConditions": True, | |||||
| "materials": {}, | |||||
| } | |||||
| with open(settings_filename) as fp: | |||||
| for line in fp: | |||||
| name, _, value = line.strip("\r\n").partition("=") | |||||
| if value.lower() == "false": | |||||
| value = False | |||||
| elif value.lower() == "true": | |||||
| value = True | |||||
| if name == "file": | |||||
| dirname = os.path.dirname(settings_filename) | |||||
| value = os.path.abspath(os.path.join(dirname, value)) | |||||
| filename = os.path.basename(value) | |||||
| settings["fileName"] = filename | |||||
| elif name.startswith("material."): | |||||
| _, _, mat_id = name.partition(".") | |||||
| settings["materials"][int(mat_id)] = { | |||||
| "markup": float(value), | |||||
| "isActive": True, | |||||
| } | |||||
| elif name == "categories": | |||||
| value = [int(c) for c in value.split(",")] | |||||
| elif name == "tags": | |||||
| value = [t for t in value.split(",")] | |||||
| settings[name] = value | |||||
| return settings_filename, settings | |||||
| def get_models(dir_name=None): | |||||
| if dir_name is None: | |||||
| dir_name = os.getcwd() | |||||
| pattern = "%s/*.ini" % (dir_name, ) | |||||
| for settings_filename in glob.iglob(pattern): | |||||
| yield parse_settings(settings_filename) | |||||
| def upload_model(settings, client): | |||||
| if not settings.get("file"): | |||||
| return False | |||||
| with open(settings["file"]) as fp: | |||||
| settings["file"] = base64.b64encode(fp.read()) | |||||
| return client.add_model(settings) | |||||