Skip to content

Commit

Permalink
enable build of pypi package (#22)
Browse files Browse the repository at this point in the history
  • Loading branch information
schiele authored May 20, 2022
1 parent 0e8bc82 commit 47feefa
Show file tree
Hide file tree
Showing 16 changed files with 191 additions and 95 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
name: Release pypi package
on:
push:
branches:
- "!*"
tags:
- "v*"
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout/@v3
- run: sed -i -e "s/^\(version = \).*/\1${GITHUB_REF_NAME/v}/" setup.cfg
- uses: actions/setup-python@v3
with:
python-version: '3.x'
- run: pip install -r test-requirements.txt
- run: pip install -e .
- run: python -m pytest
- run: python -m pylint src tests ldraw2scad
- run: python -m pycodestyle src tests ldraw2scad
- run: python -m build
- run: pip install twine
- run: python -m twine upload dist/* --verbose
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
8 changes: 5 additions & 3 deletions .github/workflows/test-python.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ jobs:
with:
python-version: '3.x'
- run: pip install -r test-requirements.txt
- run: pytest .
- run: python -m pylint *.py
- run: python -m pycodestyle *.py
- run: pip install -e .
- run: python -m pytest
- run: python -m pylint src tests ldraw2scad
- run: python -m pycodestyle src tests ldraw2scad
- run: python -m build
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
lib/
LDraw/
dist/
__pycache__/
.vscode/
test_anim/
.cache/
pytestdebug.log
*.egg-info
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Intent: Converting LDraw projects to Open SCAD to render, animate or use for oth

Requires python3, with no external python dependancies:

python ldraw-to-scad.py <ldraw file> <scad file>
ldraw2scad <ldraw file> <scad file>

Besides this basic parameters several options are available to generate results either as self-contained OpenSCAD files or relying on an LDraw OpenSCAD library that can be generated with this tool as well. Invoke the tool with the --help option for more information.

Expand All @@ -17,7 +17,7 @@ It also (naively) expects the ldraw library filenames to be lowercase.

## Testing

Install the test-requirements.txt file, then run `pytest .`.
Install the test-requirements.txt file, then run `pip install -e .` and finally `pytest .`.

## Making animations

Expand Down
88 changes: 88 additions & 0 deletions ldraw2scad
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/usr/bin/env python3

""" Translate LDraw library or file to OpenSCAD library or file. """

import os
import argparse
from ldraw_to_scad import LDrawConverter


def translate_dir(converter, src, dest, self_contained=False):
""" translate a whole model directory """
types = ['.mpd', '.ldr', '.dat']
lst = {}
for fdir, _, files in os.walk(src, followlinks=True):
rel = os.path.relpath(fdir, src)
for file in sorted(files):
base, ext = os.path.splitext(file)
key = os.path.join(rel, base)
if ext in types:
# We will now override the old extension with the new
# one. Therefore let's warn the user that the one with
# the old extension will get skipped.
if key in lst:
print(f'Skipping {os.path.join(src, key+lst[key])}')
lst[key] = ext
for key, value in lst.items():
print(f'Translating {os.path.join(src,key+value)}'
f' to {os.path.join(dest,key+".scad")}...')
converter.convert_file(os.path.join(src, key+value),
os.path.join(dest, key+".scad"),
self_contained)


def main():
""" Main function """
parser = argparse.ArgumentParser(
description='Convert an LDraw part to OpenSCAD')
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument(
'-t', '--translib', action='store_true',
help='translate the library')
parser.add_argument(
'-s', '--selfcontained', action='store_true',
help='create self-contained files')
parser.add_argument(
'-u', '--uncommented', action='store_true',
help='create uncommented files')
group.add_argument('ldraw_file', nargs='?', metavar='FILENAME',
help='source file to translate')
parser.add_argument('output_file', nargs='?', metavar='OUTPUT_FILENAME',
help='name of the translated file')
parser.add_argument(
'-l', '--lib', default=os.path.join('lib', 'ldraw'), metavar='LIB_DIR',
help='location of the LDraw parts library')
parser.add_argument(
'-o', '--openscadlibs', default='.', metavar='OPENSCAD_LIB_DIR',
help='location of the OpenSCAD libraries')
parser.add_argument(
'-n', '--libname', default='LDraw', metavar='LIB_NAME',
help='name of the OpenSCAD library')
parser.add_argument(
'--line', default=0.2, type=float, metavar='LINE_WIDTH',
help='width of lines, 0 for no lines')
args = parser.parse_args()
converter = LDrawConverter(libdir=args.lib)
converter.set('scadlibs', args.openscadlibs)
converter.set('scadlibname', args.libname)
converter.set('line', args.line)
converter.set('commented', not args.uncommented)
if args.translib:
print("Translating library...")
converter.convert_lib(args.selfcontained)
else:
if os.path.isdir(args.ldraw_file):
translate_dir(
converter, args.ldraw_file,
args.output_file if args.output_file else args.ldraw_file,
args.selfcontained)
else:
scadfile = args.output_file if args.output_file else \
os.path.splitext(args.ldraw_file)[0] + '.scad'
print(f"Translating {args.ldraw_file} to {scadfile}...")
converter.convert_file(args.ldraw_file, scadfile,
args.selfcontained)


if __name__ == '__main__':
main()
8 changes: 8 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[build-system]
requires = ["setuptools>=42"]
build-backend = "setuptools.build_meta"

[tool.pytest.ini_options]
testpaths = [
"tests",
]
6 changes: 5 additions & 1 deletion run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,9 @@
docker run --rm -v ${PWD}:/mnt/src python:3.9 bash -ceu "
cd /mnt/src &&
pip install -r test-requirements.txt &&
pytest .
pip install -e .
python -m pytest
python -m pylint src tests ldraw2scad
python -m pycodestyle src tests ldraw2scad
python -m build
"
31 changes: 31 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[metadata]
name = ldraw-to-scad
version = 0.0.0
author = Danny Staple
author_email = danny@orionrobots.co.uk
maintainer = Robert Schiele
maintainer_email = rschiele@gmail.com
description = The LDraw to OpenSCAD converter library
long_description = file: README.md
long_description_content_type = text/markdown
url = https://github.com/orionrobots/ldraw-to-scad
project_urls =
Bug Tracker = https://github.com/orionrobots/ldraw-to-scad/issues
classifiers =
Programming Language :: Python :: 3
License :: OSI Approved :: Apache Software License
Operating System :: OS Independent

[options]
package_dir =
= src
packages = find:
python_requires = >=3.6
scripts = ldraw2scad
include_package_data = True

[options.packages.find]
where = src

[options.package_data]
ldraw_to_scad = lib.scad
3 changes: 3 additions & 0 deletions src/ldraw_to_scad/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
""" the LDraw to OpenSCAD converter library """

from .ldrawconverter import *
97 changes: 11 additions & 86 deletions ldraw_to_scad.py → src/ldraw_to_scad/ldrawconverter.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
""" Translate LDraw library or file to OpenSCAD library or file. """

import os
import argparse
import pkg_resources


LIB_SCAD = pkg_resources.resource_filename(__name__, 'lib.scad')


class LDrawConverter:
Expand Down Expand Up @@ -237,25 +240,25 @@ def process_queue(self):
fdw.write(result)
self.queue[1].clear()

def convert_lib(self, selfcontained=False):
def convert_lib(self, self_contained=False):
""" Convert the whole library """
for name in self.index:
self.enqueue(name)
if selfcontained:
if self_contained:
with open(os.path.join(self.settings['scadlibs'],
self.settings['scadlibname']+'.scad'),
'w', encoding="utf-8") as fdw:
self.settings['selfcontained'] = fdw
fdw.write(self.colorfile())
with open('lib.scad', encoding="utf-8") as filedata:
with open(LIB_SCAD, encoding="utf-8") as filedata:
lines = filedata.readlines()
fdw.write(''.join(lines))
self.process_queue()
else:
os.makedirs(os.path.join(self.settings['scadlibs'],
self.settings['scadlibname']),
exist_ok=True)
with open('lib.scad', encoding="utf-8") as filedata:
with open(LIB_SCAD, encoding="utf-8") as filedata:
lines = filedata.readlines()
with open(os.path.join(self.settings['scadlibs'],
self.settings['scadlibname'], 'lib.scad'),
Expand All @@ -269,96 +272,18 @@ def convert_lib(self, selfcontained=False):
fdw.write(self.colorfile())
self.process_queue()

def convert_file(self, ldrfile, scadfile, selfcontained=False):
def convert_file(self, ldrfile, scadfile, self_contained=False):
""" Convert a single file """
self.enqueue('__main__', '/', ldrfile, scadfile)
if selfcontained:
if self_contained:
with open(scadfile, 'w', encoding="utf-8") as fdw:
self.settings['selfcontained'] = fdw
fdw.write(self.colorfile())
with open('lib.scad', encoding="utf-8") as filedata:
with open(LIB_SCAD, encoding="utf-8") as filedata:
lines = filedata.readlines()
fdw.write(''.join(lines))
fdw.write('makepoly(ldraw_lib____main__(), '
f"line={self.settings['line']});\n")
self.process_queue()
else:
self.process_queue()


def translatedir(converter, src, dest, selfcontained=False):
""" translate a whole model directory """
types = ['.mpd', '.ldr', '.dat']
lst = {}
for fdir, _, files in os.walk(src, followlinks=True):
rel = os.path.relpath(fdir, src)
for file in sorted(files):
base, ext = os.path.splitext(file)
key = os.path.join(rel, base)
if ext in types:
if key in lst:
print(f'Skipping {os.path.join(src, key+lst[key])}')
lst[key] = ext
for key, value in lst.items():
print(f'Translating {os.path.join(src,key+value)}'
f' to {os.path.join(dest,key+".scad")}...')
converter.convert_file(os.path.join(src, key+value),
os.path.join(dest, key+".scad"),
selfcontained)


def main():
""" Main function """
parser = argparse.ArgumentParser(
description='Convert an LDraw part to OpenSCAD')
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument(
'-t', '--translib', action='store_true',
help='translate the library')
parser.add_argument(
'-s', '--selfcontained', action='store_true',
help='create self-contained files')
parser.add_argument(
'-u', '--uncommented', action='store_true',
help='create uncommented files')
group.add_argument('ldraw_file', nargs='?', metavar='FILENAME',
help='source file to translate')
parser.add_argument('output_file', nargs='?', metavar='OUTPUT_FILENAME',
help='name of the translated file')
parser.add_argument(
'-l', '--lib', default=os.path.join('lib', 'ldraw'), metavar='LIB_DIR',
help='location of the LDraw parts library')
parser.add_argument(
'-o', '--openscadlibs', default='.', metavar='OPENSCAD_LIB_DIR',
help='location of the OpenSCAD libraries')
parser.add_argument(
'-n', '--libname', default='LDraw', metavar='LIB_NAME',
help='name of the OpenSCAD library')
parser.add_argument(
'--line', default=0.2, type=float, metavar='LINE_WIDTH',
help='width of lines, 0 for no lines')
args = parser.parse_args()
converter = LDrawConverter(libdir=args.lib)
converter.set('scadlibs', args.openscadlibs)
converter.set('scadlibname', args.libname)
converter.set('line', args.line)
converter.set('commented', not args.uncommented)
if args.translib:
print("Translating library...")
converter.convert_lib(args.selfcontained)
else:
if os.path.isdir(args.ldraw_file):
translatedir(
converter, args.ldraw_file,
args.output_file if args.output_file else args.ldraw_file,
args.selfcontained)
else:
scadfile = args.output_file if args.output_file else \
os.path.splitext(args.ldraw_file)[0] + '.scad'
print(f"Translating {args.ldraw_file} to {scadfile}...")
converter.convert_file(args.ldraw_file, scadfile,
args.selfcontained)


if __name__ == '__main__':
main()
File renamed without changes.
1 change: 1 addition & 0 deletions test-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ pytest
mock
pylint
pycodestyle
build
Empty file added tests/__init__.py
Empty file.
File renamed without changes.
File renamed without changes.
9 changes: 6 additions & 3 deletions test_ldraw_to_scad.py → tests/test_ldraw_to_scad.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
""" test cases for ldraw_to_scad.py """
""" test cases for ldraw_to_scad """

from unittest import TestCase
import os
Expand All @@ -7,6 +7,9 @@
from ldraw_to_scad import LDrawConverter


THIS_DIR = os.path.dirname(os.path.abspath(__file__))


class TestModule(TestCase):
""" tests for generation of function names """
def test_it_should_make_sensible_function_names(self):
Expand Down Expand Up @@ -201,7 +204,7 @@ def test_multiple_lines(self):
def test_reading_file(self):
""" test conversion of file content """
# Setup
test_file = "simple_test.dat"
test_file = os.path.join(THIS_DIR, "simple_test.dat")
# test
converter = LDrawConverter()
with open(test_file, encoding="utf-8") as fdr:
Expand Down Expand Up @@ -311,7 +314,7 @@ def test_try_simplest_mpd(self):
def test_loading_an_mpd(self):
""" test a complete MPD file """
# Setup
mpd_filename = "mpd_test.dat"
mpd_filename = os.path.join(THIS_DIR, "mpd_test.dat")
# Test
converter = LDrawConverter()
with open(mpd_filename, encoding="utf-8") as fdr:
Expand Down

0 comments on commit 47feefa

Please sign in to comment.