mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-01 08:24:53 +01:00
Merge remote-tracking branch 'origin/develop' into feature/deadline_custom_settings
This commit is contained in:
commit
bebc8d8854
46 changed files with 1595 additions and 199 deletions
57
CHANGELOG.md
57
CHANGELOG.md
|
|
@ -1,13 +1,16 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## [3.2.0-nightly.6](https://github.com/pypeclub/OpenPype/tree/HEAD)
|
## [3.2.0-nightly.7](https://github.com/pypeclub/OpenPype/tree/HEAD)
|
||||||
|
|
||||||
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/2.18.4...HEAD)
|
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/2.18.4...HEAD)
|
||||||
|
|
||||||
**🚀 Enhancements**
|
**🚀 Enhancements**
|
||||||
|
|
||||||
|
- Nuke: ftrack family plugin settings preset [\#1805](https://github.com/pypeclub/OpenPype/pull/1805)
|
||||||
|
- Standalone publisher last project [\#1799](https://github.com/pypeclub/OpenPype/pull/1799)
|
||||||
|
- Ftrack Multiple notes as server action [\#1795](https://github.com/pypeclub/OpenPype/pull/1795)
|
||||||
|
- Settings conditional dict [\#1777](https://github.com/pypeclub/OpenPype/pull/1777)
|
||||||
- Settings application use python 2 only where needed [\#1776](https://github.com/pypeclub/OpenPype/pull/1776)
|
- Settings application use python 2 only where needed [\#1776](https://github.com/pypeclub/OpenPype/pull/1776)
|
||||||
- Settings UI copy/paste [\#1769](https://github.com/pypeclub/OpenPype/pull/1769)
|
|
||||||
- Workfile tool widths [\#1766](https://github.com/pypeclub/OpenPype/pull/1766)
|
- Workfile tool widths [\#1766](https://github.com/pypeclub/OpenPype/pull/1766)
|
||||||
- Push hierarchical attributes care about task parent changes [\#1763](https://github.com/pypeclub/OpenPype/pull/1763)
|
- Push hierarchical attributes care about task parent changes [\#1763](https://github.com/pypeclub/OpenPype/pull/1763)
|
||||||
- Application executables with environment variables [\#1757](https://github.com/pypeclub/OpenPype/pull/1757)
|
- Application executables with environment variables [\#1757](https://github.com/pypeclub/OpenPype/pull/1757)
|
||||||
|
|
@ -16,18 +19,18 @@
|
||||||
- Settings Hosts enum [\#1739](https://github.com/pypeclub/OpenPype/pull/1739)
|
- Settings Hosts enum [\#1739](https://github.com/pypeclub/OpenPype/pull/1739)
|
||||||
- Validate containers settings [\#1736](https://github.com/pypeclub/OpenPype/pull/1736)
|
- Validate containers settings [\#1736](https://github.com/pypeclub/OpenPype/pull/1736)
|
||||||
- PS - added loader from sequence [\#1726](https://github.com/pypeclub/OpenPype/pull/1726)
|
- PS - added loader from sequence [\#1726](https://github.com/pypeclub/OpenPype/pull/1726)
|
||||||
- Autoupdate launcher [\#1725](https://github.com/pypeclub/OpenPype/pull/1725)
|
|
||||||
- Subset template and TVPaint subset template docs [\#1717](https://github.com/pypeclub/OpenPype/pull/1717)
|
|
||||||
- Toggle Ftrack upload in StandalonePublisher [\#1708](https://github.com/pypeclub/OpenPype/pull/1708)
|
- Toggle Ftrack upload in StandalonePublisher [\#1708](https://github.com/pypeclub/OpenPype/pull/1708)
|
||||||
- Overscan color extract review [\#1701](https://github.com/pypeclub/OpenPype/pull/1701)
|
|
||||||
- Nuke: Prerender Frame Range by default [\#1699](https://github.com/pypeclub/OpenPype/pull/1699)
|
|
||||||
- Smoother edges of color triangle [\#1695](https://github.com/pypeclub/OpenPype/pull/1695)
|
|
||||||
|
|
||||||
**🐛 Bug fixes**
|
**🐛 Bug fixes**
|
||||||
|
|
||||||
|
- nuke: fixing wrong name of family folder when `used existing frames` [\#1803](https://github.com/pypeclub/OpenPype/pull/1803)
|
||||||
|
- Collect ftrack family bugs [\#1801](https://github.com/pypeclub/OpenPype/pull/1801)
|
||||||
|
- Invitee email can be None which break the Ftrack commit. [\#1788](https://github.com/pypeclub/OpenPype/pull/1788)
|
||||||
|
- Fix: staging and `--use-version` option [\#1786](https://github.com/pypeclub/OpenPype/pull/1786)
|
||||||
- Otio unrelated error on import [\#1782](https://github.com/pypeclub/OpenPype/pull/1782)
|
- Otio unrelated error on import [\#1782](https://github.com/pypeclub/OpenPype/pull/1782)
|
||||||
- FFprobe streams order [\#1775](https://github.com/pypeclub/OpenPype/pull/1775)
|
- FFprobe streams order [\#1775](https://github.com/pypeclub/OpenPype/pull/1775)
|
||||||
- Fix - single file files are str only, cast it to list to count properly [\#1772](https://github.com/pypeclub/OpenPype/pull/1772)
|
- Fix - single file files are str only, cast it to list to count properly [\#1772](https://github.com/pypeclub/OpenPype/pull/1772)
|
||||||
|
- Environments in app executable for MacOS [\#1768](https://github.com/pypeclub/OpenPype/pull/1768)
|
||||||
- Project specific environments [\#1767](https://github.com/pypeclub/OpenPype/pull/1767)
|
- Project specific environments [\#1767](https://github.com/pypeclub/OpenPype/pull/1767)
|
||||||
- Settings UI with refresh button [\#1764](https://github.com/pypeclub/OpenPype/pull/1764)
|
- Settings UI with refresh button [\#1764](https://github.com/pypeclub/OpenPype/pull/1764)
|
||||||
- Standalone publisher thumbnail extractor fix [\#1761](https://github.com/pypeclub/OpenPype/pull/1761)
|
- Standalone publisher thumbnail extractor fix [\#1761](https://github.com/pypeclub/OpenPype/pull/1761)
|
||||||
|
|
@ -36,22 +39,18 @@
|
||||||
- hiero: precollect instances failing when audio selected [\#1743](https://github.com/pypeclub/OpenPype/pull/1743)
|
- hiero: precollect instances failing when audio selected [\#1743](https://github.com/pypeclub/OpenPype/pull/1743)
|
||||||
- Hiero: creator instance error [\#1742](https://github.com/pypeclub/OpenPype/pull/1742)
|
- Hiero: creator instance error [\#1742](https://github.com/pypeclub/OpenPype/pull/1742)
|
||||||
- Nuke: fixing render creator for no selection format failing [\#1741](https://github.com/pypeclub/OpenPype/pull/1741)
|
- Nuke: fixing render creator for no selection format failing [\#1741](https://github.com/pypeclub/OpenPype/pull/1741)
|
||||||
|
- StandalonePublisher: failing collector for editorial [\#1738](https://github.com/pypeclub/OpenPype/pull/1738)
|
||||||
- Local settings UI crash on missing defaults [\#1737](https://github.com/pypeclub/OpenPype/pull/1737)
|
- Local settings UI crash on missing defaults [\#1737](https://github.com/pypeclub/OpenPype/pull/1737)
|
||||||
- TVPaint white background on thumbnail [\#1735](https://github.com/pypeclub/OpenPype/pull/1735)
|
- TVPaint white background on thumbnail [\#1735](https://github.com/pypeclub/OpenPype/pull/1735)
|
||||||
- Ftrack missing custom attribute message [\#1734](https://github.com/pypeclub/OpenPype/pull/1734)
|
|
||||||
- Launcher project changes [\#1733](https://github.com/pypeclub/OpenPype/pull/1733)
|
|
||||||
- Ftrack sync status [\#1732](https://github.com/pypeclub/OpenPype/pull/1732)
|
|
||||||
- TVPaint use layer name for default variant [\#1724](https://github.com/pypeclub/OpenPype/pull/1724)
|
|
||||||
- Default subset template for TVPaint review and workfile families [\#1716](https://github.com/pypeclub/OpenPype/pull/1716)
|
|
||||||
- Maya: Extract review hotfix [\#1714](https://github.com/pypeclub/OpenPype/pull/1714)
|
|
||||||
- Settings: Imageio improving granularity [\#1711](https://github.com/pypeclub/OpenPype/pull/1711)
|
|
||||||
- Application without executables [\#1679](https://github.com/pypeclub/OpenPype/pull/1679)
|
- Application without executables [\#1679](https://github.com/pypeclub/OpenPype/pull/1679)
|
||||||
|
- Unreal: launching on Linux [\#1672](https://github.com/pypeclub/OpenPype/pull/1672)
|
||||||
|
|
||||||
**Merged pull requests:**
|
**Merged pull requests:**
|
||||||
|
|
||||||
|
- Build: don't add Poetry to `PATH` [\#1808](https://github.com/pypeclub/OpenPype/pull/1808)
|
||||||
- Bump prismjs from 1.23.0 to 1.24.0 in /website [\#1773](https://github.com/pypeclub/OpenPype/pull/1773)
|
- Bump prismjs from 1.23.0 to 1.24.0 in /website [\#1773](https://github.com/pypeclub/OpenPype/pull/1773)
|
||||||
|
- Bc/fix/docs [\#1771](https://github.com/pypeclub/OpenPype/pull/1771)
|
||||||
- TVPaint ftrack family [\#1755](https://github.com/pypeclub/OpenPype/pull/1755)
|
- TVPaint ftrack family [\#1755](https://github.com/pypeclub/OpenPype/pull/1755)
|
||||||
- Sync main 2.x back to 2.x develop [\#1715](https://github.com/pypeclub/OpenPype/pull/1715)
|
|
||||||
|
|
||||||
## [2.18.4](https://github.com/pypeclub/OpenPype/tree/2.18.4) (2021-06-24)
|
## [2.18.4](https://github.com/pypeclub/OpenPype/tree/2.18.4) (2021-06-24)
|
||||||
|
|
||||||
|
|
@ -66,26 +65,21 @@
|
||||||
|
|
||||||
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.2.0-nightly.2...2.18.3)
|
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.2.0-nightly.2...2.18.3)
|
||||||
|
|
||||||
**🚀 Enhancements**
|
|
||||||
|
|
||||||
- Log Viewer with OpenPype style [\#1703](https://github.com/pypeclub/OpenPype/pull/1703)
|
|
||||||
|
|
||||||
**🐛 Bug fixes**
|
**🐛 Bug fixes**
|
||||||
|
|
||||||
- Tools names forwards compatibility [\#1727](https://github.com/pypeclub/OpenPype/pull/1727)
|
- Tools names forwards compatibility [\#1727](https://github.com/pypeclub/OpenPype/pull/1727)
|
||||||
|
|
||||||
|
**Merged pull requests:**
|
||||||
|
|
||||||
|
- global: removing obsolete ftrack validator plugin [\#1710](https://github.com/pypeclub/OpenPype/pull/1710)
|
||||||
|
|
||||||
## [2.18.2](https://github.com/pypeclub/OpenPype/tree/2.18.2) (2021-06-16)
|
## [2.18.2](https://github.com/pypeclub/OpenPype/tree/2.18.2) (2021-06-16)
|
||||||
|
|
||||||
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.1.0...2.18.2)
|
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.1.0...2.18.2)
|
||||||
|
|
||||||
**🚀 Enhancements**
|
|
||||||
|
|
||||||
- StandalonePublisher: adding exception for adding `delete` tag to repre [\#1650](https://github.com/pypeclub/OpenPype/pull/1650)
|
|
||||||
|
|
||||||
**🐛 Bug fixes**
|
**🐛 Bug fixes**
|
||||||
|
|
||||||
- Maya: Extract review hotfix - 2.x backport [\#1713](https://github.com/pypeclub/OpenPype/pull/1713)
|
- Maya: Extract review hotfix - 2.x backport [\#1713](https://github.com/pypeclub/OpenPype/pull/1713)
|
||||||
- StandalonePublisher: instance data attribute `keepSequence` [\#1668](https://github.com/pypeclub/OpenPype/pull/1668)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
**Merged pull requests:**
|
||||||
|
|
||||||
|
|
@ -97,19 +91,12 @@
|
||||||
|
|
||||||
**🚀 Enhancements**
|
**🚀 Enhancements**
|
||||||
|
|
||||||
|
- Log Viewer with OpenPype style [\#1703](https://github.com/pypeclub/OpenPype/pull/1703)
|
||||||
- Scrolling in OpenPype info widget [\#1702](https://github.com/pypeclub/OpenPype/pull/1702)
|
- Scrolling in OpenPype info widget [\#1702](https://github.com/pypeclub/OpenPype/pull/1702)
|
||||||
- OpenPype style in modules [\#1694](https://github.com/pypeclub/OpenPype/pull/1694)
|
- OpenPype style in modules [\#1694](https://github.com/pypeclub/OpenPype/pull/1694)
|
||||||
- Sort applications and tools alphabetically in Settings UI [\#1689](https://github.com/pypeclub/OpenPype/pull/1689)
|
- Sort applications and tools alphabetically in Settings UI [\#1689](https://github.com/pypeclub/OpenPype/pull/1689)
|
||||||
- \#683 - Validate Frame Range in Standalone Publisher [\#1683](https://github.com/pypeclub/OpenPype/pull/1683)
|
- \#683 - Validate Frame Range in Standalone Publisher [\#1683](https://github.com/pypeclub/OpenPype/pull/1683)
|
||||||
- Hiero: old container versions identify with red color [\#1682](https://github.com/pypeclub/OpenPype/pull/1682)
|
- Hiero: old container versions identify with red color [\#1682](https://github.com/pypeclub/OpenPype/pull/1682)
|
||||||
- Project Manger: Default name column width [\#1669](https://github.com/pypeclub/OpenPype/pull/1669)
|
|
||||||
- Remove outline in stylesheet [\#1667](https://github.com/pypeclub/OpenPype/pull/1667)
|
|
||||||
- TVPaint: Creator take layer name as default value for subset variant [\#1663](https://github.com/pypeclub/OpenPype/pull/1663)
|
|
||||||
- TVPaint custom subset template [\#1662](https://github.com/pypeclub/OpenPype/pull/1662)
|
|
||||||
- Editorial: conform assets validator [\#1659](https://github.com/pypeclub/OpenPype/pull/1659)
|
|
||||||
- Feature Slack integration [\#1657](https://github.com/pypeclub/OpenPype/pull/1657)
|
|
||||||
- Nuke - Publish simplification [\#1653](https://github.com/pypeclub/OpenPype/pull/1653)
|
|
||||||
- \#1333 - added tooltip hints to Pyblish buttons [\#1649](https://github.com/pypeclub/OpenPype/pull/1649)
|
|
||||||
|
|
||||||
**🐛 Bug fixes**
|
**🐛 Bug fixes**
|
||||||
|
|
||||||
|
|
@ -119,15 +106,9 @@
|
||||||
- Hiero: published whole edit mov [\#1687](https://github.com/pypeclub/OpenPype/pull/1687)
|
- Hiero: published whole edit mov [\#1687](https://github.com/pypeclub/OpenPype/pull/1687)
|
||||||
- Ftrack subprocess handle of stdout/stderr [\#1675](https://github.com/pypeclub/OpenPype/pull/1675)
|
- Ftrack subprocess handle of stdout/stderr [\#1675](https://github.com/pypeclub/OpenPype/pull/1675)
|
||||||
- Settings list race condifiton and mutable dict list conversion [\#1671](https://github.com/pypeclub/OpenPype/pull/1671)
|
- Settings list race condifiton and mutable dict list conversion [\#1671](https://github.com/pypeclub/OpenPype/pull/1671)
|
||||||
- Mac launch arguments fix [\#1660](https://github.com/pypeclub/OpenPype/pull/1660)
|
|
||||||
- Fix missing dbm python module [\#1652](https://github.com/pypeclub/OpenPype/pull/1652)
|
|
||||||
- Transparent branches in view on Mac [\#1648](https://github.com/pypeclub/OpenPype/pull/1648)
|
|
||||||
- Add asset on task item [\#1646](https://github.com/pypeclub/OpenPype/pull/1646)
|
|
||||||
- Project manager save and queue [\#1645](https://github.com/pypeclub/OpenPype/pull/1645)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
**Merged pull requests:**
|
||||||
|
|
||||||
- global: removing obsolete ftrack validator plugin [\#1710](https://github.com/pypeclub/OpenPype/pull/1710)
|
|
||||||
- update dependencies [\#1697](https://github.com/pypeclub/OpenPype/pull/1697)
|
- update dependencies [\#1697](https://github.com/pypeclub/OpenPype/pull/1697)
|
||||||
- Bump normalize-url from 4.5.0 to 4.5.1 in /website [\#1686](https://github.com/pypeclub/OpenPype/pull/1686)
|
- Bump normalize-url from 4.5.0 to 4.5.1 in /website [\#1686](https://github.com/pypeclub/OpenPype/pull/1686)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ class CollectInstances(pyblish.api.ContextPlugin):
|
||||||
# Create nice name if the instance has a frame range.
|
# Create nice name if the instance has a frame range.
|
||||||
label = data.get("name", node.name())
|
label = data.get("name", node.name())
|
||||||
if "frameStart" in data and "frameEnd" in data:
|
if "frameStart" in data and "frameEnd" in data:
|
||||||
frames = "[{startFrame} - {endFrame}]".format(**data)
|
frames = "[{frameStart} - {frameEnd}]".format(**data)
|
||||||
label = "{} {}".format(label, frames)
|
label = "{} {}".format(label, frames)
|
||||||
|
|
||||||
instance = context.create_instance(label)
|
instance = context.create_instance(label)
|
||||||
|
|
|
||||||
|
|
@ -70,8 +70,9 @@ class PreCollectNukeInstances(pyblish.api.ContextPlugin):
|
||||||
review = False
|
review = False
|
||||||
if "review" in node.knobs():
|
if "review" in node.knobs():
|
||||||
review = node["review"].value()
|
review = node["review"].value()
|
||||||
|
|
||||||
|
if review:
|
||||||
families.append("review")
|
families.append("review")
|
||||||
families.append("ftrack")
|
|
||||||
|
|
||||||
# Add all nodes in group instances.
|
# Add all nodes in group instances.
|
||||||
if node.Class() == "Group":
|
if node.Class() == "Group":
|
||||||
|
|
@ -81,18 +82,18 @@ class PreCollectNukeInstances(pyblish.api.ContextPlugin):
|
||||||
if target == "Use existing frames":
|
if target == "Use existing frames":
|
||||||
# Local rendering
|
# Local rendering
|
||||||
self.log.info("flagged for no render")
|
self.log.info("flagged for no render")
|
||||||
families.append(family)
|
families.append(families_ak.lower())
|
||||||
elif target == "Local":
|
elif target == "Local":
|
||||||
# Local rendering
|
# Local rendering
|
||||||
self.log.info("flagged for local render")
|
self.log.info("flagged for local render")
|
||||||
families.append("{}.local".format(family))
|
families.append("{}.local".format(family))
|
||||||
|
family = families_ak.lower()
|
||||||
elif target == "On farm":
|
elif target == "On farm":
|
||||||
# Farm rendering
|
# Farm rendering
|
||||||
self.log.info("flagged for farm render")
|
self.log.info("flagged for farm render")
|
||||||
instance.data["transfer"] = False
|
instance.data["transfer"] = False
|
||||||
families.append("{}.farm".format(family))
|
families.append("{}.farm".format(family))
|
||||||
|
family = families_ak.lower()
|
||||||
family = families_ak.lower()
|
|
||||||
|
|
||||||
node.begin()
|
node.begin()
|
||||||
for i in nuke.allNodes():
|
for i in nuke.allNodes():
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ class CollectInstances(pyblish.api.InstancePlugin):
|
||||||
"""Collect instances from editorial's OTIO sequence"""
|
"""Collect instances from editorial's OTIO sequence"""
|
||||||
|
|
||||||
order = pyblish.api.CollectorOrder + 0.01
|
order = pyblish.api.CollectorOrder + 0.01
|
||||||
label = "Collect Instances"
|
label = "Collect Editorial Instances"
|
||||||
hosts = ["standalonepublisher"]
|
hosts = ["standalonepublisher"]
|
||||||
families = ["editorial"]
|
families = ["editorial"]
|
||||||
|
|
||||||
|
|
@ -55,7 +55,7 @@ class CollectInstances(pyblish.api.InstancePlugin):
|
||||||
fps = plib.get_asset()["data"]["fps"]
|
fps = plib.get_asset()["data"]["fps"]
|
||||||
|
|
||||||
tracks = timeline.each_child(
|
tracks = timeline.each_child(
|
||||||
descended_from_type=otio.schema.track.Track
|
descended_from_type=otio.schema.Track
|
||||||
)
|
)
|
||||||
|
|
||||||
# get data from avalon
|
# get data from avalon
|
||||||
|
|
@ -84,6 +84,9 @@ class CollectInstances(pyblish.api.InstancePlugin):
|
||||||
if clip.name is None:
|
if clip.name is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if isinstance(clip, otio.schema.Gap):
|
||||||
|
continue
|
||||||
|
|
||||||
# skip all generators like black ampty
|
# skip all generators like black ampty
|
||||||
if isinstance(
|
if isinstance(
|
||||||
clip.media_reference,
|
clip.media_reference,
|
||||||
|
|
@ -92,7 +95,7 @@ class CollectInstances(pyblish.api.InstancePlugin):
|
||||||
|
|
||||||
# Transitions are ignored, because Clips have the full frame
|
# Transitions are ignored, because Clips have the full frame
|
||||||
# range.
|
# range.
|
||||||
if isinstance(clip, otio.schema.transition.Transition):
|
if isinstance(clip, otio.schema.Transition):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# basic unique asset name
|
# basic unique asset name
|
||||||
|
|
@ -11,7 +11,7 @@ class CollectInstanceResources(pyblish.api.InstancePlugin):
|
||||||
|
|
||||||
# must be after `CollectInstances`
|
# must be after `CollectInstances`
|
||||||
order = pyblish.api.CollectorOrder + 0.011
|
order = pyblish.api.CollectorOrder + 0.011
|
||||||
label = "Collect Instance Resources"
|
label = "Collect Editorial Resources"
|
||||||
hosts = ["standalonepublisher"]
|
hosts = ["standalonepublisher"]
|
||||||
families = ["clip"]
|
families = ["clip"]
|
||||||
|
|
||||||
|
|
@ -449,6 +449,12 @@ class ApplicationExecutable:
|
||||||
"""Representation of executable loaded from settings."""
|
"""Representation of executable loaded from settings."""
|
||||||
|
|
||||||
def __init__(self, executable):
|
def __init__(self, executable):
|
||||||
|
# Try to format executable with environments
|
||||||
|
try:
|
||||||
|
executable = executable.format(**os.environ)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
# On MacOS check if exists path to executable when ends with `.app`
|
# On MacOS check if exists path to executable when ends with `.app`
|
||||||
# - it is common that path will lead to "/Applications/Blender" but
|
# - it is common that path will lead to "/Applications/Blender" but
|
||||||
# real path is "/Applications/Blender.app"
|
# real path is "/Applications/Blender.app"
|
||||||
|
|
@ -460,12 +466,6 @@ class ApplicationExecutable:
|
||||||
if os.path.exists(_executable):
|
if os.path.exists(_executable):
|
||||||
executable = _executable
|
executable = _executable
|
||||||
|
|
||||||
# Try to format executable with environments
|
|
||||||
try:
|
|
||||||
executable = executable.format(**os.environ)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
self.executable_path = executable
|
self.executable_path = executable
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,167 @@
|
||||||
|
from openpype.modules.ftrack.lib import ServerAction
|
||||||
|
|
||||||
|
|
||||||
|
class MultipleNotesServer(ServerAction):
|
||||||
|
"""Action adds same note for muliple AssetVersions.
|
||||||
|
|
||||||
|
Note is added to selection of AssetVersions. Note is created with user
|
||||||
|
who triggered the action. It is possible to define note category of note.
|
||||||
|
"""
|
||||||
|
|
||||||
|
identifier = "multiple.notes.server"
|
||||||
|
label = "Multiple Notes (Server)"
|
||||||
|
description = "Add same note to multiple Asset Versions"
|
||||||
|
|
||||||
|
_none_category = "__NONE__"
|
||||||
|
|
||||||
|
def discover(self, session, entities, event):
|
||||||
|
"""Show action only on AssetVersions."""
|
||||||
|
if not entities:
|
||||||
|
return False
|
||||||
|
|
||||||
|
for entity in entities:
|
||||||
|
if entity.entity_type.lower() != "assetversion":
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def interface(self, session, entities, event):
|
||||||
|
event_source = event["source"]
|
||||||
|
user_info = event_source.get("user") or {}
|
||||||
|
user_id = user_info.get("id")
|
||||||
|
if not user_id:
|
||||||
|
return None
|
||||||
|
|
||||||
|
values = event["data"].get("values")
|
||||||
|
if values:
|
||||||
|
return None
|
||||||
|
|
||||||
|
note_label = {
|
||||||
|
"type": "label",
|
||||||
|
"value": "# Enter note: #"
|
||||||
|
}
|
||||||
|
|
||||||
|
note_value = {
|
||||||
|
"name": "note",
|
||||||
|
"type": "textarea"
|
||||||
|
}
|
||||||
|
|
||||||
|
category_label = {
|
||||||
|
"type": "label",
|
||||||
|
"value": "## Category: ##"
|
||||||
|
}
|
||||||
|
|
||||||
|
category_data = []
|
||||||
|
category_data.append({
|
||||||
|
"label": "- None -",
|
||||||
|
"value": self._none_category
|
||||||
|
})
|
||||||
|
all_categories = session.query(
|
||||||
|
"select id, name from NoteCategory"
|
||||||
|
).all()
|
||||||
|
for cat in all_categories:
|
||||||
|
category_data.append({
|
||||||
|
"label": cat["name"],
|
||||||
|
"value": cat["id"]
|
||||||
|
})
|
||||||
|
category_value = {
|
||||||
|
"type": "enumerator",
|
||||||
|
"name": "category",
|
||||||
|
"data": category_data,
|
||||||
|
"value": self._none_category
|
||||||
|
}
|
||||||
|
|
||||||
|
splitter = {
|
||||||
|
"type": "label",
|
||||||
|
"value": "---"
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
note_label,
|
||||||
|
note_value,
|
||||||
|
splitter,
|
||||||
|
category_label,
|
||||||
|
category_value
|
||||||
|
]
|
||||||
|
|
||||||
|
def launch(self, session, entities, event):
|
||||||
|
if "values" not in event["data"]:
|
||||||
|
return None
|
||||||
|
|
||||||
|
values = event["data"]["values"]
|
||||||
|
if len(values) <= 0 or "note" not in values:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Get Note text
|
||||||
|
note_value = values["note"]
|
||||||
|
if note_value.lower().strip() == "":
|
||||||
|
return {
|
||||||
|
"success": True,
|
||||||
|
"message": "Note was not entered. Skipping"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get User
|
||||||
|
event_source = event["source"]
|
||||||
|
user_info = event_source.get("user") or {}
|
||||||
|
user_id = user_info.get("id")
|
||||||
|
user = None
|
||||||
|
if user_id:
|
||||||
|
user = session.query(
|
||||||
|
'User where id is "{}"'.format(user_id)
|
||||||
|
).first()
|
||||||
|
|
||||||
|
if not user:
|
||||||
|
return {
|
||||||
|
"success": False,
|
||||||
|
"message": "Couldn't get user information."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Logging message preparation
|
||||||
|
# - username
|
||||||
|
username = user.get("username") or "N/A"
|
||||||
|
|
||||||
|
# - AssetVersion ids
|
||||||
|
asset_version_ids_str = ",".join([entity["id"] for entity in entities])
|
||||||
|
|
||||||
|
# Base note data
|
||||||
|
note_data = {
|
||||||
|
"content": note_value,
|
||||||
|
"author": user
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get category
|
||||||
|
category_id = values["category"]
|
||||||
|
if category_id == self._none_category:
|
||||||
|
category_id = None
|
||||||
|
|
||||||
|
category_name = None
|
||||||
|
if category_id is not None:
|
||||||
|
category = session.query(
|
||||||
|
"select id, name from NoteCategory where id is \"{}\"".format(
|
||||||
|
category_id
|
||||||
|
)
|
||||||
|
).first()
|
||||||
|
if category:
|
||||||
|
note_data["category"] = category
|
||||||
|
category_name = category["name"]
|
||||||
|
|
||||||
|
category_msg = ""
|
||||||
|
if category_name:
|
||||||
|
category_msg = " with category: \"{}\"".format(category_name)
|
||||||
|
|
||||||
|
self.log.warning((
|
||||||
|
"Creating note{} as User \"{}\" on "
|
||||||
|
"AssetVersions: {} with value \"{}\""
|
||||||
|
).format(category_msg, username, asset_version_ids_str, note_value))
|
||||||
|
|
||||||
|
# Create notes for entities
|
||||||
|
for entity in entities:
|
||||||
|
new_note = session.create("Note", note_data)
|
||||||
|
entity["notes"].append(new_note)
|
||||||
|
session.commit()
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def register(session):
|
||||||
|
'''Register plugin. Called when used as an plugin.'''
|
||||||
|
|
||||||
|
MultipleNotesServer(session).register()
|
||||||
|
|
@ -51,7 +51,7 @@ class CollectFtrackFamily(pyblish.api.InstancePlugin):
|
||||||
families = instance.data.get("families")
|
families = instance.data.get("families")
|
||||||
add_ftrack_family = profile["add_ftrack_family"]
|
add_ftrack_family = profile["add_ftrack_family"]
|
||||||
|
|
||||||
additional_filters = profile.get("additional_filters")
|
additional_filters = profile.get("advanced_filtering")
|
||||||
if additional_filters:
|
if additional_filters:
|
||||||
add_ftrack_family = self._get_add_ftrack_f_from_addit_filters(
|
add_ftrack_family = self._get_add_ftrack_f_from_addit_filters(
|
||||||
additional_filters,
|
additional_filters,
|
||||||
|
|
|
||||||
|
|
@ -229,7 +229,6 @@
|
||||||
"standalonepublisher"
|
"standalonepublisher"
|
||||||
],
|
],
|
||||||
"families": [
|
"families": [
|
||||||
"review",
|
|
||||||
"plate"
|
"plate"
|
||||||
],
|
],
|
||||||
"tasks": [],
|
"tasks": [],
|
||||||
|
|
@ -279,6 +278,25 @@
|
||||||
"tasks": [],
|
"tasks": [],
|
||||||
"add_ftrack_family": true,
|
"add_ftrack_family": true,
|
||||||
"advanced_filtering": []
|
"advanced_filtering": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hosts": [
|
||||||
|
"nuke"
|
||||||
|
],
|
||||||
|
"families": [
|
||||||
|
"write",
|
||||||
|
"render"
|
||||||
|
],
|
||||||
|
"tasks": [],
|
||||||
|
"add_ftrack_family": false,
|
||||||
|
"advanced_filtering": [
|
||||||
|
{
|
||||||
|
"families": [
|
||||||
|
"review"
|
||||||
|
],
|
||||||
|
"add_ftrack_family": true
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,7 @@ from .enum_entity import (
|
||||||
from .list_entity import ListEntity
|
from .list_entity import ListEntity
|
||||||
from .dict_immutable_keys_entity import DictImmutableKeysEntity
|
from .dict_immutable_keys_entity import DictImmutableKeysEntity
|
||||||
from .dict_mutable_keys_entity import DictMutableKeysEntity
|
from .dict_mutable_keys_entity import DictMutableKeysEntity
|
||||||
|
from .dict_conditional import DictConditionalEntity
|
||||||
|
|
||||||
from .anatomy_entities import AnatomyEntity
|
from .anatomy_entities import AnatomyEntity
|
||||||
|
|
||||||
|
|
@ -166,5 +167,7 @@ __all__ = (
|
||||||
|
|
||||||
"DictMutableKeysEntity",
|
"DictMutableKeysEntity",
|
||||||
|
|
||||||
|
"DictConditionalEntity",
|
||||||
|
|
||||||
"AnatomyEntity"
|
"AnatomyEntity"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,7 @@ class BaseItemEntity(BaseEntity):
|
||||||
# Override state defines which values are used, saved and how.
|
# Override state defines which values are used, saved and how.
|
||||||
# TODO convert to private attribute
|
# TODO convert to private attribute
|
||||||
self._override_state = OverrideState.NOT_DEFINED
|
self._override_state = OverrideState.NOT_DEFINED
|
||||||
|
self._ignore_missing_defaults = None
|
||||||
|
|
||||||
# These attributes may change values during existence of an object
|
# These attributes may change values during existence of an object
|
||||||
# Default value, studio override values and project override values
|
# Default value, studio override values and project override values
|
||||||
|
|
@ -285,7 +286,7 @@ class BaseItemEntity(BaseEntity):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def set_override_state(self, state):
|
def set_override_state(self, state, ignore_missing_defaults):
|
||||||
"""Set override state and trigger it on children.
|
"""Set override state and trigger it on children.
|
||||||
|
|
||||||
Method discard all changes in hierarchy and use values, metadata
|
Method discard all changes in hierarchy and use values, metadata
|
||||||
|
|
@ -295,8 +296,15 @@ class BaseItemEntity(BaseEntity):
|
||||||
Should start on root entity and when triggered then must be called on
|
Should start on root entity and when triggered then must be called on
|
||||||
all entities in hierarchy.
|
all entities in hierarchy.
|
||||||
|
|
||||||
|
Argument `ignore_missing_defaults` should be used when entity has
|
||||||
|
children that are not saved or used all the time but override statu
|
||||||
|
must be changed and children must have any default value.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
state (OverrideState): State to which should be data changed.
|
state (OverrideState): State to which should be data changed.
|
||||||
|
ignore_missing_defaults (bool): Ignore missing default values.
|
||||||
|
Entity won't raise `DefaultsNotDefined` and
|
||||||
|
`StudioDefaultsNotDefined`.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
||||||
707
openpype/settings/entities/dict_conditional.py
Normal file
707
openpype/settings/entities/dict_conditional.py
Normal file
|
|
@ -0,0 +1,707 @@
|
||||||
|
import copy
|
||||||
|
|
||||||
|
from .lib import (
|
||||||
|
OverrideState,
|
||||||
|
NOT_SET
|
||||||
|
)
|
||||||
|
from openpype.settings.constants import (
|
||||||
|
METADATA_KEYS,
|
||||||
|
M_OVERRIDEN_KEY,
|
||||||
|
KEY_REGEX
|
||||||
|
)
|
||||||
|
from . import (
|
||||||
|
BaseItemEntity,
|
||||||
|
ItemEntity,
|
||||||
|
GUIEntity
|
||||||
|
)
|
||||||
|
from .exceptions import (
|
||||||
|
SchemaDuplicatedKeys,
|
||||||
|
EntitySchemaError,
|
||||||
|
InvalidKeySymbols
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class DictConditionalEntity(ItemEntity):
|
||||||
|
"""Entity represents dictionay with only one persistent key definition.
|
||||||
|
|
||||||
|
The persistent key is enumerator which define rest of children under
|
||||||
|
dictionary. There is not possibility of shared children.
|
||||||
|
|
||||||
|
Entity's keys can't be removed or added. But they may change based on
|
||||||
|
the persistent key. If you're change value manually (key by key) make sure
|
||||||
|
you'll change value of the persistent key as first. It is recommended to
|
||||||
|
use `set` method which handle this for you.
|
||||||
|
|
||||||
|
It is possible to use entity similar way as `dict` object. Returned values
|
||||||
|
are not real settings values but entities representing the value.
|
||||||
|
"""
|
||||||
|
schema_types = ["dict-conditional"]
|
||||||
|
_default_label_wrap = {
|
||||||
|
"use_label_wrap": False,
|
||||||
|
"collapsible": False,
|
||||||
|
"collapsed": True
|
||||||
|
}
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
"""Return entity inder key."""
|
||||||
|
if key == self.enum_key:
|
||||||
|
return self.enum_entity
|
||||||
|
return self.non_gui_children[self.current_enum][key]
|
||||||
|
|
||||||
|
def __setitem__(self, key, value):
|
||||||
|
"""Set value of item under key."""
|
||||||
|
if key == self.enum_key:
|
||||||
|
child_obj = self.enum_entity
|
||||||
|
else:
|
||||||
|
child_obj = self.non_gui_children[self.current_enum][key]
|
||||||
|
child_obj.set(value)
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
"""Iter through keys."""
|
||||||
|
for key in self.keys():
|
||||||
|
yield key
|
||||||
|
|
||||||
|
def __contains__(self, key):
|
||||||
|
"""Check if key is available."""
|
||||||
|
if key == self.enum_key:
|
||||||
|
return True
|
||||||
|
return key in self.non_gui_children[self.current_enum]
|
||||||
|
|
||||||
|
def get(self, key, default=None):
|
||||||
|
"""Safe entity getter by key."""
|
||||||
|
if key == self.enum_key:
|
||||||
|
return self.enum_entity
|
||||||
|
return self.non_gui_children[self.current_enum].get(key, default)
|
||||||
|
|
||||||
|
def keys(self):
|
||||||
|
"""Entity's keys."""
|
||||||
|
keys = list(self.non_gui_children[self.current_enum].keys())
|
||||||
|
keys.insert(0, [self.enum_key])
|
||||||
|
return keys
|
||||||
|
|
||||||
|
def values(self):
|
||||||
|
"""Children entities."""
|
||||||
|
values = [
|
||||||
|
self.enum_entity
|
||||||
|
]
|
||||||
|
for child_entiy in self.non_gui_children[self.current_enum].values():
|
||||||
|
values.append(child_entiy)
|
||||||
|
return values
|
||||||
|
|
||||||
|
def items(self):
|
||||||
|
"""Children entities paired with their key (key, value)."""
|
||||||
|
items = [
|
||||||
|
(self.enum_key, self.enum_entity)
|
||||||
|
]
|
||||||
|
for key, value in self.non_gui_children[self.current_enum].items():
|
||||||
|
items.append((key, value))
|
||||||
|
return items
|
||||||
|
|
||||||
|
def set(self, value):
|
||||||
|
"""Set value."""
|
||||||
|
new_value = self.convert_to_valid_type(value)
|
||||||
|
# First change value of enum key if available
|
||||||
|
if self.enum_key in new_value:
|
||||||
|
self.enum_entity.set(new_value.pop(self.enum_key))
|
||||||
|
|
||||||
|
for _key, _value in new_value.items():
|
||||||
|
self.non_gui_children[self.current_enum][_key].set(_value)
|
||||||
|
|
||||||
|
def _item_initalization(self):
|
||||||
|
self._default_metadata = NOT_SET
|
||||||
|
self._studio_override_metadata = NOT_SET
|
||||||
|
self._project_override_metadata = NOT_SET
|
||||||
|
|
||||||
|
self._ignore_child_changes = False
|
||||||
|
|
||||||
|
# `current_metadata` are still when schema is loaded
|
||||||
|
# - only metadata stored with dict item are gorup overrides in
|
||||||
|
# M_OVERRIDEN_KEY
|
||||||
|
self._current_metadata = {}
|
||||||
|
self._metadata_are_modified = False
|
||||||
|
|
||||||
|
# Entity must be group or in group
|
||||||
|
if (
|
||||||
|
self.group_item is None
|
||||||
|
and not self.is_dynamic_item
|
||||||
|
and not self.is_in_dynamic_item
|
||||||
|
):
|
||||||
|
self.is_group = True
|
||||||
|
|
||||||
|
# Children are stored by key as keys are immutable and are defined by
|
||||||
|
# schema
|
||||||
|
self.valid_value_types = (dict, )
|
||||||
|
self.children = {}
|
||||||
|
self.non_gui_children = {}
|
||||||
|
self.gui_layout = {}
|
||||||
|
|
||||||
|
if self.is_dynamic_item:
|
||||||
|
self.require_key = False
|
||||||
|
|
||||||
|
self.enum_key = self.schema_data.get("enum_key")
|
||||||
|
self.enum_label = self.schema_data.get("enum_label")
|
||||||
|
self.enum_children = self.schema_data.get("enum_children")
|
||||||
|
|
||||||
|
self.enum_entity = None
|
||||||
|
|
||||||
|
self.highlight_content = self.schema_data.get(
|
||||||
|
"highlight_content", False
|
||||||
|
)
|
||||||
|
self.show_borders = self.schema_data.get("show_borders", True)
|
||||||
|
|
||||||
|
self._add_children()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def current_enum(self):
|
||||||
|
"""Current value of enum entity.
|
||||||
|
|
||||||
|
This value define what children are used.
|
||||||
|
"""
|
||||||
|
if self.enum_entity is None:
|
||||||
|
return None
|
||||||
|
return self.enum_entity.value
|
||||||
|
|
||||||
|
def schema_validations(self):
|
||||||
|
"""Validation of schema data."""
|
||||||
|
# Enum key must be defined
|
||||||
|
if self.enum_key is None:
|
||||||
|
raise EntitySchemaError(self, "Key 'enum_key' is not set.")
|
||||||
|
|
||||||
|
# Validate type of enum children
|
||||||
|
if not isinstance(self.enum_children, list):
|
||||||
|
raise EntitySchemaError(
|
||||||
|
self, "Key 'enum_children' must be a list. Got: {}".format(
|
||||||
|
str(type(self.enum_children))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Without defined enum children entity has nothing to do
|
||||||
|
if not self.enum_children:
|
||||||
|
raise EntitySchemaError(self, (
|
||||||
|
"Key 'enum_children' have empty value. Entity can't work"
|
||||||
|
" without children definitions."
|
||||||
|
))
|
||||||
|
|
||||||
|
children_def_keys = []
|
||||||
|
for children_def in self.enum_children:
|
||||||
|
if not isinstance(children_def, dict):
|
||||||
|
raise EntitySchemaError((
|
||||||
|
"Children definition under key 'enum_children' must"
|
||||||
|
" be a dictionary."
|
||||||
|
))
|
||||||
|
|
||||||
|
if "key" not in children_def:
|
||||||
|
raise EntitySchemaError((
|
||||||
|
"Children definition under key 'enum_children' miss"
|
||||||
|
" 'key' definition."
|
||||||
|
))
|
||||||
|
# We don't validate regex of these keys because they will be stored
|
||||||
|
# as value at the end.
|
||||||
|
key = children_def["key"]
|
||||||
|
if key in children_def_keys:
|
||||||
|
# TODO this hould probably be different exception?
|
||||||
|
raise SchemaDuplicatedKeys(self, key)
|
||||||
|
children_def_keys.append(key)
|
||||||
|
|
||||||
|
# Validate key duplications per each enum item
|
||||||
|
for children in self.children.values():
|
||||||
|
children_keys = set()
|
||||||
|
children_keys.add(self.enum_key)
|
||||||
|
for child_entity in children:
|
||||||
|
if not isinstance(child_entity, BaseItemEntity):
|
||||||
|
continue
|
||||||
|
elif child_entity.key not in children_keys:
|
||||||
|
children_keys.add(child_entity.key)
|
||||||
|
else:
|
||||||
|
raise SchemaDuplicatedKeys(self, child_entity.key)
|
||||||
|
|
||||||
|
# Enum key must match key regex
|
||||||
|
if not KEY_REGEX.match(self.enum_key):
|
||||||
|
raise InvalidKeySymbols(self.path, self.enum_key)
|
||||||
|
|
||||||
|
# Validate all remaining keys with key regex
|
||||||
|
for children_by_key in self.non_gui_children.values():
|
||||||
|
for key in children_by_key.keys():
|
||||||
|
if not KEY_REGEX.match(key):
|
||||||
|
raise InvalidKeySymbols(self.path, key)
|
||||||
|
|
||||||
|
super(DictConditionalEntity, self).schema_validations()
|
||||||
|
# Trigger schema validation on children entities
|
||||||
|
for children in self.children.values():
|
||||||
|
for child_obj in children:
|
||||||
|
child_obj.schema_validations()
|
||||||
|
|
||||||
|
def on_change(self):
|
||||||
|
"""Update metadata on change and pass change to parent."""
|
||||||
|
self._update_current_metadata()
|
||||||
|
|
||||||
|
for callback in self.on_change_callbacks:
|
||||||
|
callback()
|
||||||
|
self.parent.on_child_change(self)
|
||||||
|
|
||||||
|
def on_child_change(self, child_obj):
|
||||||
|
"""Trigger on change callback if child changes are not ignored."""
|
||||||
|
if self._ignore_child_changes:
|
||||||
|
return
|
||||||
|
|
||||||
|
if (
|
||||||
|
child_obj is self.enum_entity
|
||||||
|
or child_obj in self.children[self.current_enum]
|
||||||
|
):
|
||||||
|
self.on_change()
|
||||||
|
|
||||||
|
def _add_children(self):
|
||||||
|
"""Add children from schema data and repare enum items.
|
||||||
|
|
||||||
|
Each enum item must have defined it's children. None are shared across
|
||||||
|
all enum items.
|
||||||
|
|
||||||
|
Nice to have: Have ability to have shared keys across all enum items.
|
||||||
|
|
||||||
|
All children are stored by their enum item.
|
||||||
|
"""
|
||||||
|
# Skip if are not defined
|
||||||
|
# - schema validations should raise and exception
|
||||||
|
if not self.enum_children or not self.enum_key:
|
||||||
|
return
|
||||||
|
|
||||||
|
valid_enum_items = []
|
||||||
|
for item in self.enum_children:
|
||||||
|
if isinstance(item, dict) and "key" in item:
|
||||||
|
valid_enum_items.append(item)
|
||||||
|
|
||||||
|
enum_items = []
|
||||||
|
for item in valid_enum_items:
|
||||||
|
item_key = item["key"]
|
||||||
|
item_label = item.get("label") or item_key
|
||||||
|
enum_items.append({item_key: item_label})
|
||||||
|
|
||||||
|
if not enum_items:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Create Enum child first
|
||||||
|
enum_key = self.enum_key or "invalid"
|
||||||
|
enum_schema = {
|
||||||
|
"type": "enum",
|
||||||
|
"multiselection": False,
|
||||||
|
"enum_items": enum_items,
|
||||||
|
"key": enum_key,
|
||||||
|
"label": self.enum_label or enum_key
|
||||||
|
}
|
||||||
|
|
||||||
|
enum_entity = self.create_schema_object(enum_schema, self)
|
||||||
|
self.enum_entity = enum_entity
|
||||||
|
|
||||||
|
# Create children per each enum item
|
||||||
|
for item in valid_enum_items:
|
||||||
|
item_key = item["key"]
|
||||||
|
# Make sure all keys have set value in these variables
|
||||||
|
# - key 'children' is optional
|
||||||
|
self.non_gui_children[item_key] = {}
|
||||||
|
self.children[item_key] = []
|
||||||
|
self.gui_layout[item_key] = []
|
||||||
|
|
||||||
|
children = item.get("children") or []
|
||||||
|
for children_schema in children:
|
||||||
|
child_obj = self.create_schema_object(children_schema, self)
|
||||||
|
self.children[item_key].append(child_obj)
|
||||||
|
self.gui_layout[item_key].append(child_obj)
|
||||||
|
if isinstance(child_obj, GUIEntity):
|
||||||
|
continue
|
||||||
|
|
||||||
|
self.non_gui_children[item_key][child_obj.key] = child_obj
|
||||||
|
|
||||||
|
def get_child_path(self, child_obj):
|
||||||
|
"""Get hierarchical path of child entity.
|
||||||
|
|
||||||
|
Child must be entity's direct children. This must be possible to get
|
||||||
|
for any children even if not from current enum value.
|
||||||
|
"""
|
||||||
|
if child_obj is self.enum_entity:
|
||||||
|
return "/".join([self.path, self.enum_key])
|
||||||
|
|
||||||
|
result_key = None
|
||||||
|
for children in self.non_gui_children.values():
|
||||||
|
for key, _child_obj in children.items():
|
||||||
|
if _child_obj is child_obj:
|
||||||
|
result_key = key
|
||||||
|
break
|
||||||
|
|
||||||
|
if result_key is None:
|
||||||
|
raise ValueError("Didn't found child {}".format(child_obj))
|
||||||
|
|
||||||
|
return "/".join([self.path, result_key])
|
||||||
|
|
||||||
|
def _update_current_metadata(self):
|
||||||
|
current_metadata = {}
|
||||||
|
for key, child_obj in self.non_gui_children[self.current_enum].items():
|
||||||
|
if self._override_state is OverrideState.DEFAULTS:
|
||||||
|
break
|
||||||
|
|
||||||
|
if not child_obj.is_group:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if (
|
||||||
|
self._override_state is OverrideState.STUDIO
|
||||||
|
and not child_obj.has_studio_override
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if (
|
||||||
|
self._override_state is OverrideState.PROJECT
|
||||||
|
and not child_obj.has_project_override
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if M_OVERRIDEN_KEY not in current_metadata:
|
||||||
|
current_metadata[M_OVERRIDEN_KEY] = []
|
||||||
|
current_metadata[M_OVERRIDEN_KEY].append(key)
|
||||||
|
|
||||||
|
# Define if current metadata are avaialble for current override state
|
||||||
|
metadata = NOT_SET
|
||||||
|
if self._override_state is OverrideState.STUDIO:
|
||||||
|
metadata = self._studio_override_metadata
|
||||||
|
|
||||||
|
elif self._override_state is OverrideState.PROJECT:
|
||||||
|
metadata = self._project_override_metadata
|
||||||
|
|
||||||
|
if metadata is NOT_SET:
|
||||||
|
metadata = {}
|
||||||
|
|
||||||
|
self._metadata_are_modified = current_metadata != metadata
|
||||||
|
self._current_metadata = current_metadata
|
||||||
|
|
||||||
|
def set_override_state(self, state, ignore_missing_defaults):
|
||||||
|
# Trigger override state change of root if is not same
|
||||||
|
if self.root_item.override_state is not state:
|
||||||
|
self.root_item.set_override_state(state)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Change has/had override states
|
||||||
|
self._override_state = state
|
||||||
|
self._ignore_missing_defaults = ignore_missing_defaults
|
||||||
|
|
||||||
|
# Set override state on enum entity first
|
||||||
|
self.enum_entity.set_override_state(state, ignore_missing_defaults)
|
||||||
|
|
||||||
|
# Set override state on other enum children
|
||||||
|
# - these must not raise exception about missing defaults
|
||||||
|
for children_by_key in self.non_gui_children.values():
|
||||||
|
for child_obj in children_by_key.values():
|
||||||
|
child_obj.set_override_state(state, True)
|
||||||
|
|
||||||
|
self._update_current_metadata()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def value(self):
|
||||||
|
output = {
|
||||||
|
self.enum_key: self.enum_entity.value
|
||||||
|
}
|
||||||
|
for key, child_obj in self.non_gui_children[self.current_enum].items():
|
||||||
|
output[key] = child_obj.value
|
||||||
|
return output
|
||||||
|
|
||||||
|
@property
|
||||||
|
def has_unsaved_changes(self):
|
||||||
|
if self._metadata_are_modified:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return self._child_has_unsaved_changes
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _child_has_unsaved_changes(self):
|
||||||
|
if self.enum_entity.has_unsaved_changes:
|
||||||
|
return True
|
||||||
|
|
||||||
|
for child_obj in self.non_gui_children[self.current_enum].values():
|
||||||
|
if child_obj.has_unsaved_changes:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def has_studio_override(self):
|
||||||
|
return self._child_has_studio_override
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _child_has_studio_override(self):
|
||||||
|
if self._override_state >= OverrideState.STUDIO:
|
||||||
|
if self.enum_entity.has_studio_override:
|
||||||
|
return True
|
||||||
|
|
||||||
|
for child_obj in self.non_gui_children[self.current_enum].values():
|
||||||
|
if child_obj.has_studio_override:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def has_project_override(self):
|
||||||
|
return self._child_has_project_override
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _child_has_project_override(self):
|
||||||
|
if self._override_state >= OverrideState.PROJECT:
|
||||||
|
if self.enum_entity.has_project_override:
|
||||||
|
return True
|
||||||
|
|
||||||
|
for child_obj in self.non_gui_children[self.current_enum].values():
|
||||||
|
if child_obj.has_project_override:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def settings_value(self):
|
||||||
|
if self._override_state is OverrideState.NOT_DEFINED:
|
||||||
|
return NOT_SET
|
||||||
|
|
||||||
|
if self._override_state is OverrideState.DEFAULTS:
|
||||||
|
children_items = [
|
||||||
|
(self.enum_key, self.enum_entity)
|
||||||
|
]
|
||||||
|
for item in self.non_gui_children[self.current_enum].items():
|
||||||
|
children_items.append(item)
|
||||||
|
|
||||||
|
output = {}
|
||||||
|
for key, child_obj in children_items:
|
||||||
|
child_value = child_obj.settings_value()
|
||||||
|
if not child_obj.is_file and not child_obj.file_item:
|
||||||
|
for _key, _value in child_value.items():
|
||||||
|
new_key = "/".join([key, _key])
|
||||||
|
output[new_key] = _value
|
||||||
|
else:
|
||||||
|
output[key] = child_value
|
||||||
|
return output
|
||||||
|
|
||||||
|
if self.is_group:
|
||||||
|
if self._override_state is OverrideState.STUDIO:
|
||||||
|
if not self.has_studio_override:
|
||||||
|
return NOT_SET
|
||||||
|
elif self._override_state is OverrideState.PROJECT:
|
||||||
|
if not self.has_project_override:
|
||||||
|
return NOT_SET
|
||||||
|
|
||||||
|
output = {}
|
||||||
|
children_items = [
|
||||||
|
(self.enum_key, self.enum_entity)
|
||||||
|
]
|
||||||
|
for item in self.non_gui_children[self.current_enum].items():
|
||||||
|
children_items.append(item)
|
||||||
|
|
||||||
|
for key, child_obj in children_items:
|
||||||
|
value = child_obj.settings_value()
|
||||||
|
if value is not NOT_SET:
|
||||||
|
output[key] = value
|
||||||
|
|
||||||
|
if not output:
|
||||||
|
return NOT_SET
|
||||||
|
|
||||||
|
output.update(self._current_metadata)
|
||||||
|
return output
|
||||||
|
|
||||||
|
def _prepare_value(self, value):
|
||||||
|
if value is NOT_SET or self.enum_key not in value:
|
||||||
|
return NOT_SET, NOT_SET
|
||||||
|
|
||||||
|
enum_value = value.get(self.enum_key)
|
||||||
|
if enum_value not in self.non_gui_children:
|
||||||
|
return NOT_SET, NOT_SET
|
||||||
|
|
||||||
|
# Create copy of value before poping values
|
||||||
|
value = copy.deepcopy(value)
|
||||||
|
metadata = {}
|
||||||
|
for key in METADATA_KEYS:
|
||||||
|
if key in value:
|
||||||
|
metadata[key] = value.pop(key)
|
||||||
|
|
||||||
|
enum_value = value.get(self.enum_key)
|
||||||
|
|
||||||
|
old_metadata = metadata.get(M_OVERRIDEN_KEY)
|
||||||
|
if old_metadata:
|
||||||
|
old_metadata_set = set(old_metadata)
|
||||||
|
new_metadata = []
|
||||||
|
non_gui_children = self.non_gui_children[enum_value]
|
||||||
|
for key in non_gui_children.keys():
|
||||||
|
if key in old_metadata:
|
||||||
|
new_metadata.append(key)
|
||||||
|
old_metadata_set.remove(key)
|
||||||
|
|
||||||
|
for key in old_metadata_set:
|
||||||
|
new_metadata.append(key)
|
||||||
|
metadata[M_OVERRIDEN_KEY] = new_metadata
|
||||||
|
|
||||||
|
return value, metadata
|
||||||
|
|
||||||
|
def update_default_value(self, value):
|
||||||
|
"""Update default values.
|
||||||
|
|
||||||
|
Not an api method, should be called by parent.
|
||||||
|
"""
|
||||||
|
value = self._check_update_value(value, "default")
|
||||||
|
self.has_default_value = value is not NOT_SET
|
||||||
|
# TODO add value validation
|
||||||
|
value, metadata = self._prepare_value(value)
|
||||||
|
self._default_metadata = metadata
|
||||||
|
|
||||||
|
if value is NOT_SET:
|
||||||
|
self.enum_entity.update_default_value(value)
|
||||||
|
for children_by_key in self.non_gui_children.values():
|
||||||
|
for child_obj in children_by_key.values():
|
||||||
|
child_obj.update_default_value(value)
|
||||||
|
return
|
||||||
|
|
||||||
|
value_keys = set(value.keys())
|
||||||
|
enum_value = value[self.enum_key]
|
||||||
|
expected_keys = set(self.non_gui_children[enum_value].keys())
|
||||||
|
expected_keys.add(self.enum_key)
|
||||||
|
unknown_keys = value_keys - expected_keys
|
||||||
|
if unknown_keys:
|
||||||
|
self.log.warning(
|
||||||
|
"{} Unknown keys in default values: {}".format(
|
||||||
|
self.path,
|
||||||
|
", ".join("\"{}\"".format(key) for key in unknown_keys)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.enum_entity.update_default_value(enum_value)
|
||||||
|
for children_by_key in self.non_gui_children.values():
|
||||||
|
for key, child_obj in children_by_key.items():
|
||||||
|
child_value = value.get(key, NOT_SET)
|
||||||
|
child_obj.update_default_value(child_value)
|
||||||
|
|
||||||
|
def update_studio_value(self, value):
|
||||||
|
"""Update studio override values.
|
||||||
|
|
||||||
|
Not an api method, should be called by parent.
|
||||||
|
"""
|
||||||
|
value = self._check_update_value(value, "studio override")
|
||||||
|
value, metadata = self._prepare_value(value)
|
||||||
|
self._studio_override_metadata = metadata
|
||||||
|
self.had_studio_override = metadata is not NOT_SET
|
||||||
|
|
||||||
|
if value is NOT_SET:
|
||||||
|
self.enum_entity.update_studio_value(value)
|
||||||
|
for children_by_key in self.non_gui_children.values():
|
||||||
|
for child_obj in children_by_key.values():
|
||||||
|
child_obj.update_studio_value(value)
|
||||||
|
return
|
||||||
|
|
||||||
|
value_keys = set(value.keys())
|
||||||
|
enum_value = value[self.enum_key]
|
||||||
|
expected_keys = set(self.non_gui_children[enum_value])
|
||||||
|
expected_keys.add(self.enum_key)
|
||||||
|
unknown_keys = value_keys - expected_keys
|
||||||
|
if unknown_keys:
|
||||||
|
self.log.warning(
|
||||||
|
"{} Unknown keys in studio overrides: {}".format(
|
||||||
|
self.path,
|
||||||
|
", ".join("\"{}\"".format(key) for key in unknown_keys)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.enum_entity.update_studio_value(enum_value)
|
||||||
|
for children_by_key in self.non_gui_children.values():
|
||||||
|
for key, child_obj in children_by_key.items():
|
||||||
|
child_value = value.get(key, NOT_SET)
|
||||||
|
child_obj.update_studio_value(child_value)
|
||||||
|
|
||||||
|
def update_project_value(self, value):
|
||||||
|
"""Update project override values.
|
||||||
|
|
||||||
|
Not an api method, should be called by parent.
|
||||||
|
"""
|
||||||
|
value = self._check_update_value(value, "project override")
|
||||||
|
value, metadata = self._prepare_value(value)
|
||||||
|
self._project_override_metadata = metadata
|
||||||
|
self.had_project_override = metadata is not NOT_SET
|
||||||
|
|
||||||
|
if value is NOT_SET:
|
||||||
|
self.enum_entity.update_project_value(value)
|
||||||
|
for children_by_key in self.non_gui_children.values():
|
||||||
|
for child_obj in children_by_key.values():
|
||||||
|
child_obj.update_project_value(value)
|
||||||
|
return
|
||||||
|
|
||||||
|
value_keys = set(value.keys())
|
||||||
|
enum_value = value[self.enum_key]
|
||||||
|
expected_keys = set(self.non_gui_children[enum_value])
|
||||||
|
expected_keys.add(self.enum_key)
|
||||||
|
unknown_keys = value_keys - expected_keys
|
||||||
|
if unknown_keys:
|
||||||
|
self.log.warning(
|
||||||
|
"{} Unknown keys in project overrides: {}".format(
|
||||||
|
self.path,
|
||||||
|
", ".join("\"{}\"".format(key) for key in unknown_keys)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.enum_entity.update_project_value(enum_value)
|
||||||
|
for children_by_key in self.non_gui_children.values():
|
||||||
|
for key, child_obj in children_by_key.items():
|
||||||
|
child_value = value.get(key, NOT_SET)
|
||||||
|
child_obj.update_project_value(child_value)
|
||||||
|
|
||||||
|
def _discard_changes(self, on_change_trigger):
|
||||||
|
self._ignore_child_changes = True
|
||||||
|
|
||||||
|
self.enum_entity.discard_changes(on_change_trigger)
|
||||||
|
for children_by_key in self.non_gui_children.values():
|
||||||
|
for child_obj in children_by_key.values():
|
||||||
|
child_obj.discard_changes(on_change_trigger)
|
||||||
|
|
||||||
|
self._ignore_child_changes = False
|
||||||
|
|
||||||
|
def _add_to_studio_default(self, on_change_trigger):
|
||||||
|
self._ignore_child_changes = True
|
||||||
|
|
||||||
|
self.enum_entity.add_to_studio_default(on_change_trigger)
|
||||||
|
for children_by_key in self.non_gui_children.values():
|
||||||
|
for child_obj in children_by_key.values():
|
||||||
|
child_obj.add_to_studio_default(on_change_trigger)
|
||||||
|
|
||||||
|
self._ignore_child_changes = False
|
||||||
|
|
||||||
|
self._update_current_metadata()
|
||||||
|
|
||||||
|
self.parent.on_child_change(self)
|
||||||
|
|
||||||
|
def _remove_from_studio_default(self, on_change_trigger):
|
||||||
|
self._ignore_child_changes = True
|
||||||
|
|
||||||
|
self.enum_entity.remove_from_studio_default(on_change_trigger)
|
||||||
|
for children_by_key in self.non_gui_children.values():
|
||||||
|
for child_obj in children_by_key.values():
|
||||||
|
child_obj.remove_from_studio_default(on_change_trigger)
|
||||||
|
|
||||||
|
self._ignore_child_changes = False
|
||||||
|
|
||||||
|
def _add_to_project_override(self, on_change_trigger):
|
||||||
|
self._ignore_child_changes = True
|
||||||
|
|
||||||
|
self.enum_entity.add_to_project_override(on_change_trigger)
|
||||||
|
for children_by_key in self.non_gui_children.values():
|
||||||
|
for child_obj in children_by_key.values():
|
||||||
|
child_obj.add_to_project_override(on_change_trigger)
|
||||||
|
|
||||||
|
self._ignore_child_changes = False
|
||||||
|
|
||||||
|
self._update_current_metadata()
|
||||||
|
|
||||||
|
self.parent.on_child_change(self)
|
||||||
|
|
||||||
|
def _remove_from_project_override(self, on_change_trigger):
|
||||||
|
if self._override_state is not OverrideState.PROJECT:
|
||||||
|
return
|
||||||
|
|
||||||
|
self._ignore_child_changes = True
|
||||||
|
|
||||||
|
self.enum_entity.remove_from_project_override(on_change_trigger)
|
||||||
|
for children_by_key in self.non_gui_children.values():
|
||||||
|
for child_obj in children_by_key.values():
|
||||||
|
child_obj.remove_from_project_override(on_change_trigger)
|
||||||
|
|
||||||
|
self._ignore_child_changes = False
|
||||||
|
|
||||||
|
def reset_callbacks(self):
|
||||||
|
"""Reset registered callbacks on entity and children."""
|
||||||
|
super(DictConditionalEntity, self).reset_callbacks()
|
||||||
|
for children in self.children.values():
|
||||||
|
for child_entity in children:
|
||||||
|
child_entity.reset_callbacks()
|
||||||
|
|
@ -258,7 +258,7 @@ class DictImmutableKeysEntity(ItemEntity):
|
||||||
self._metadata_are_modified = current_metadata != metadata
|
self._metadata_are_modified = current_metadata != metadata
|
||||||
self._current_metadata = current_metadata
|
self._current_metadata = current_metadata
|
||||||
|
|
||||||
def set_override_state(self, state):
|
def set_override_state(self, state, ignore_missing_defaults):
|
||||||
# Trigger override state change of root if is not same
|
# Trigger override state change of root if is not same
|
||||||
if self.root_item.override_state is not state:
|
if self.root_item.override_state is not state:
|
||||||
self.root_item.set_override_state(state)
|
self.root_item.set_override_state(state)
|
||||||
|
|
@ -266,9 +266,10 @@ class DictImmutableKeysEntity(ItemEntity):
|
||||||
|
|
||||||
# Change has/had override states
|
# Change has/had override states
|
||||||
self._override_state = state
|
self._override_state = state
|
||||||
|
self._ignore_missing_defaults = ignore_missing_defaults
|
||||||
|
|
||||||
for child_obj in self.non_gui_children.values():
|
for child_obj in self.non_gui_children.values():
|
||||||
child_obj.set_override_state(state)
|
child_obj.set_override_state(state, ignore_missing_defaults)
|
||||||
|
|
||||||
self._update_current_metadata()
|
self._update_current_metadata()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,9 @@ class DictMutableKeysEntity(EndpointEntity):
|
||||||
|
|
||||||
def add_key(self, key):
|
def add_key(self, key):
|
||||||
new_child = self._add_key(key)
|
new_child = self._add_key(key)
|
||||||
new_child.set_override_state(self._override_state)
|
new_child.set_override_state(
|
||||||
|
self._override_state, self._ignore_missing_defaults
|
||||||
|
)
|
||||||
self.on_change()
|
self.on_change()
|
||||||
return new_child
|
return new_child
|
||||||
|
|
||||||
|
|
@ -320,7 +322,7 @@ class DictMutableKeysEntity(EndpointEntity):
|
||||||
def _metadata_for_current_state(self):
|
def _metadata_for_current_state(self):
|
||||||
return self._get_metadata_for_state(self._override_state)
|
return self._get_metadata_for_state(self._override_state)
|
||||||
|
|
||||||
def set_override_state(self, state):
|
def set_override_state(self, state, ignore_missing_defaults):
|
||||||
# Trigger override state change of root if is not same
|
# Trigger override state change of root if is not same
|
||||||
if self.root_item.override_state is not state:
|
if self.root_item.override_state is not state:
|
||||||
self.root_item.set_override_state(state)
|
self.root_item.set_override_state(state)
|
||||||
|
|
@ -328,14 +330,22 @@ class DictMutableKeysEntity(EndpointEntity):
|
||||||
|
|
||||||
# TODO change metadata
|
# TODO change metadata
|
||||||
self._override_state = state
|
self._override_state = state
|
||||||
|
self._ignore_missing_defaults = ignore_missing_defaults
|
||||||
|
|
||||||
# Ignore if is dynamic item and use default in that case
|
# Ignore if is dynamic item and use default in that case
|
||||||
if not self.is_dynamic_item and not self.is_in_dynamic_item:
|
if not self.is_dynamic_item and not self.is_in_dynamic_item:
|
||||||
if state > OverrideState.DEFAULTS:
|
if state > OverrideState.DEFAULTS:
|
||||||
if not self.has_default_value:
|
if (
|
||||||
|
not self.has_default_value
|
||||||
|
and not ignore_missing_defaults
|
||||||
|
):
|
||||||
raise DefaultsNotDefined(self)
|
raise DefaultsNotDefined(self)
|
||||||
|
|
||||||
elif state > OverrideState.STUDIO:
|
elif state > OverrideState.STUDIO:
|
||||||
if not self.had_studio_override:
|
if (
|
||||||
|
not self.had_studio_override
|
||||||
|
and not ignore_missing_defaults
|
||||||
|
):
|
||||||
raise StudioDefaultsNotDefined(self)
|
raise StudioDefaultsNotDefined(self)
|
||||||
|
|
||||||
if state is OverrideState.STUDIO:
|
if state is OverrideState.STUDIO:
|
||||||
|
|
@ -426,7 +436,7 @@ class DictMutableKeysEntity(EndpointEntity):
|
||||||
|
|
||||||
if label:
|
if label:
|
||||||
children_label_by_id[child_entity.id] = label
|
children_label_by_id[child_entity.id] = label
|
||||||
child_entity.set_override_state(state)
|
child_entity.set_override_state(state, ignore_missing_defaults)
|
||||||
|
|
||||||
self.children_label_by_id = children_label_by_id
|
self.children_label_by_id = children_label_by_id
|
||||||
|
|
||||||
|
|
@ -610,7 +620,9 @@ class DictMutableKeysEntity(EndpointEntity):
|
||||||
if not self._can_discard_changes:
|
if not self._can_discard_changes:
|
||||||
return
|
return
|
||||||
|
|
||||||
self.set_override_state(self._override_state)
|
self.set_override_state(
|
||||||
|
self._override_state, self._ignore_missing_defaults
|
||||||
|
)
|
||||||
on_change_trigger.append(self.on_change)
|
on_change_trigger.append(self.on_change)
|
||||||
|
|
||||||
def _add_to_studio_default(self, _on_change_trigger):
|
def _add_to_studio_default(self, _on_change_trigger):
|
||||||
|
|
@ -645,7 +657,9 @@ class DictMutableKeysEntity(EndpointEntity):
|
||||||
if label:
|
if label:
|
||||||
children_label_by_id[child_entity.id] = label
|
children_label_by_id[child_entity.id] = label
|
||||||
|
|
||||||
child_entity.set_override_state(self._override_state)
|
child_entity.set_override_state(
|
||||||
|
self._override_state, self._ignore_missing_defaults
|
||||||
|
)
|
||||||
|
|
||||||
self.children_label_by_id = children_label_by_id
|
self.children_label_by_id = children_label_by_id
|
||||||
|
|
||||||
|
|
@ -694,7 +708,9 @@ class DictMutableKeysEntity(EndpointEntity):
|
||||||
if label:
|
if label:
|
||||||
children_label_by_id[child_entity.id] = label
|
children_label_by_id[child_entity.id] = label
|
||||||
|
|
||||||
child_entity.set_override_state(self._override_state)
|
child_entity.set_override_state(
|
||||||
|
self._override_state, self._ignore_missing_defaults
|
||||||
|
)
|
||||||
|
|
||||||
self.children_label_by_id = children_label_by_id
|
self.children_label_by_id = children_label_by_id
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -217,21 +217,28 @@ class InputEntity(EndpointEntity):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def set_override_state(self, state):
|
def set_override_state(self, state, ignore_missing_defaults):
|
||||||
# Trigger override state change of root if is not same
|
# Trigger override state change of root if is not same
|
||||||
if self.root_item.override_state is not state:
|
if self.root_item.override_state is not state:
|
||||||
self.root_item.set_override_state(state)
|
self.root_item.set_override_state(state)
|
||||||
return
|
return
|
||||||
|
|
||||||
self._override_state = state
|
self._override_state = state
|
||||||
|
self._ignore_missing_defaults = ignore_missing_defaults
|
||||||
# Ignore if is dynamic item and use default in that case
|
# Ignore if is dynamic item and use default in that case
|
||||||
if not self.is_dynamic_item and not self.is_in_dynamic_item:
|
if not self.is_dynamic_item and not self.is_in_dynamic_item:
|
||||||
if state > OverrideState.DEFAULTS:
|
if state > OverrideState.DEFAULTS:
|
||||||
if not self.has_default_value:
|
if (
|
||||||
|
not self.has_default_value
|
||||||
|
and not ignore_missing_defaults
|
||||||
|
):
|
||||||
raise DefaultsNotDefined(self)
|
raise DefaultsNotDefined(self)
|
||||||
|
|
||||||
elif state > OverrideState.STUDIO:
|
elif state > OverrideState.STUDIO:
|
||||||
if not self.had_studio_override:
|
if (
|
||||||
|
not self.had_studio_override
|
||||||
|
and not ignore_missing_defaults
|
||||||
|
):
|
||||||
raise StudioDefaultsNotDefined(self)
|
raise StudioDefaultsNotDefined(self)
|
||||||
|
|
||||||
if state is OverrideState.STUDIO:
|
if state is OverrideState.STUDIO:
|
||||||
|
|
|
||||||
|
|
@ -150,14 +150,15 @@ class PathEntity(ItemEntity):
|
||||||
def value(self):
|
def value(self):
|
||||||
return self.child_obj.value
|
return self.child_obj.value
|
||||||
|
|
||||||
def set_override_state(self, state):
|
def set_override_state(self, state, ignore_missing_defaults):
|
||||||
# Trigger override state change of root if is not same
|
# Trigger override state change of root if is not same
|
||||||
if self.root_item.override_state is not state:
|
if self.root_item.override_state is not state:
|
||||||
self.root_item.set_override_state(state)
|
self.root_item.set_override_state(state)
|
||||||
return
|
return
|
||||||
|
|
||||||
self._override_state = state
|
self._override_state = state
|
||||||
self.child_obj.set_override_state(state)
|
self._ignore_missing_defaults = ignore_missing_defaults
|
||||||
|
self.child_obj.set_override_state(state, ignore_missing_defaults)
|
||||||
|
|
||||||
def update_default_value(self, value):
|
def update_default_value(self, value):
|
||||||
self.child_obj.update_default_value(value)
|
self.child_obj.update_default_value(value)
|
||||||
|
|
@ -344,25 +345,32 @@ class ListStrictEntity(ItemEntity):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def set_override_state(self, state):
|
def set_override_state(self, state, ignore_missing_defaults):
|
||||||
# Trigger override state change of root if is not same
|
# Trigger override state change of root if is not same
|
||||||
if self.root_item.override_state is not state:
|
if self.root_item.override_state is not state:
|
||||||
self.root_item.set_override_state(state)
|
self.root_item.set_override_state(state)
|
||||||
return
|
return
|
||||||
|
|
||||||
self._override_state = state
|
self._override_state = state
|
||||||
|
self._ignore_missing_defaults = ignore_missing_defaults
|
||||||
# Ignore if is dynamic item and use default in that case
|
# Ignore if is dynamic item and use default in that case
|
||||||
if not self.is_dynamic_item and not self.is_in_dynamic_item:
|
if not self.is_dynamic_item and not self.is_in_dynamic_item:
|
||||||
if state > OverrideState.DEFAULTS:
|
if state > OverrideState.DEFAULTS:
|
||||||
if not self.has_default_value:
|
if (
|
||||||
|
not self.has_default_value
|
||||||
|
and not ignore_missing_defaults
|
||||||
|
):
|
||||||
raise DefaultsNotDefined(self)
|
raise DefaultsNotDefined(self)
|
||||||
|
|
||||||
elif state > OverrideState.STUDIO:
|
elif state > OverrideState.STUDIO:
|
||||||
if not self.had_studio_override:
|
if (
|
||||||
|
not self.had_studio_override
|
||||||
|
and not ignore_missing_defaults
|
||||||
|
):
|
||||||
raise StudioDefaultsNotDefined(self)
|
raise StudioDefaultsNotDefined(self)
|
||||||
|
|
||||||
for child_entity in self.children:
|
for child_entity in self.children:
|
||||||
child_entity.set_override_state(state)
|
child_entity.set_override_state(state, ignore_missing_defaults)
|
||||||
|
|
||||||
self.initial_value = self.settings_value()
|
self.initial_value = self.settings_value()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@ class SchemasHub:
|
||||||
crashed_item = self._crashed_on_load[schema_name]
|
crashed_item = self._crashed_on_load[schema_name]
|
||||||
raise KeyError(
|
raise KeyError(
|
||||||
"Unable to parse schema file \"{}\". {}".format(
|
"Unable to parse schema file \"{}\". {}".format(
|
||||||
crashed_item["filpath"], crashed_item["message"]
|
crashed_item["filepath"], crashed_item["message"]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -176,8 +176,8 @@ class SchemasHub:
|
||||||
elif template_name in self._crashed_on_load:
|
elif template_name in self._crashed_on_load:
|
||||||
crashed_item = self._crashed_on_load[template_name]
|
crashed_item = self._crashed_on_load[template_name]
|
||||||
raise KeyError(
|
raise KeyError(
|
||||||
"Unable to parse templace file \"{}\". {}".format(
|
"Unable to parse template file \"{}\". {}".format(
|
||||||
crashed_item["filpath"], crashed_item["message"]
|
crashed_item["filepath"], crashed_item["message"]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -345,7 +345,7 @@ class SchemasHub:
|
||||||
" One of them crashed on load \"{}\" {}"
|
" One of them crashed on load \"{}\" {}"
|
||||||
).format(
|
).format(
|
||||||
filename,
|
filename,
|
||||||
crashed_item["filpath"],
|
crashed_item["filepath"],
|
||||||
crashed_item["message"]
|
crashed_item["message"]
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,9 @@ class ListEntity(EndpointEntity):
|
||||||
|
|
||||||
def add_new_item(self, idx=None, trigger_change=True):
|
def add_new_item(self, idx=None, trigger_change=True):
|
||||||
child_obj = self._add_new_item(idx)
|
child_obj = self._add_new_item(idx)
|
||||||
child_obj.set_override_state(self._override_state)
|
child_obj.set_override_state(
|
||||||
|
self._override_state, self._ignore_missing_defaults
|
||||||
|
)
|
||||||
|
|
||||||
if trigger_change:
|
if trigger_change:
|
||||||
self.on_child_change(child_obj)
|
self.on_child_change(child_obj)
|
||||||
|
|
@ -205,13 +207,14 @@ class ListEntity(EndpointEntity):
|
||||||
self._has_project_override = True
|
self._has_project_override = True
|
||||||
self.on_change()
|
self.on_change()
|
||||||
|
|
||||||
def set_override_state(self, state):
|
def set_override_state(self, state, ignore_missing_defaults):
|
||||||
# Trigger override state change of root if is not same
|
# Trigger override state change of root if is not same
|
||||||
if self.root_item.override_state is not state:
|
if self.root_item.override_state is not state:
|
||||||
self.root_item.set_override_state(state)
|
self.root_item.set_override_state(state)
|
||||||
return
|
return
|
||||||
|
|
||||||
self._override_state = state
|
self._override_state = state
|
||||||
|
self._ignore_missing_defaults = ignore_missing_defaults
|
||||||
|
|
||||||
while self.children:
|
while self.children:
|
||||||
self.children.pop(0)
|
self.children.pop(0)
|
||||||
|
|
@ -219,11 +222,17 @@ class ListEntity(EndpointEntity):
|
||||||
# Ignore if is dynamic item and use default in that case
|
# Ignore if is dynamic item and use default in that case
|
||||||
if not self.is_dynamic_item and not self.is_in_dynamic_item:
|
if not self.is_dynamic_item and not self.is_in_dynamic_item:
|
||||||
if state > OverrideState.DEFAULTS:
|
if state > OverrideState.DEFAULTS:
|
||||||
if not self.has_default_value:
|
if (
|
||||||
|
not self.has_default_value
|
||||||
|
and not ignore_missing_defaults
|
||||||
|
):
|
||||||
raise DefaultsNotDefined(self)
|
raise DefaultsNotDefined(self)
|
||||||
|
|
||||||
elif state > OverrideState.STUDIO:
|
elif state > OverrideState.STUDIO:
|
||||||
if not self.had_studio_override:
|
if (
|
||||||
|
not self.had_studio_override
|
||||||
|
and not ignore_missing_defaults
|
||||||
|
):
|
||||||
raise StudioDefaultsNotDefined(self)
|
raise StudioDefaultsNotDefined(self)
|
||||||
|
|
||||||
value = NOT_SET
|
value = NOT_SET
|
||||||
|
|
@ -257,7 +266,9 @@ class ListEntity(EndpointEntity):
|
||||||
child_obj.update_studio_value(item)
|
child_obj.update_studio_value(item)
|
||||||
|
|
||||||
for child_obj in self.children:
|
for child_obj in self.children:
|
||||||
child_obj.set_override_state(self._override_state)
|
child_obj.set_override_state(
|
||||||
|
self._override_state, ignore_missing_defaults
|
||||||
|
)
|
||||||
|
|
||||||
self.initial_value = self.settings_value()
|
self.initial_value = self.settings_value()
|
||||||
|
|
||||||
|
|
@ -395,7 +406,9 @@ class ListEntity(EndpointEntity):
|
||||||
if self.had_studio_override:
|
if self.had_studio_override:
|
||||||
child_obj.update_studio_value(item)
|
child_obj.update_studio_value(item)
|
||||||
|
|
||||||
child_obj.set_override_state(self._override_state)
|
child_obj.set_override_state(
|
||||||
|
self._override_state, self._ignore_missing_defaults
|
||||||
|
)
|
||||||
|
|
||||||
if self._override_state >= OverrideState.PROJECT:
|
if self._override_state >= OverrideState.PROJECT:
|
||||||
self._has_project_override = self.had_project_override
|
self._has_project_override = self.had_project_override
|
||||||
|
|
@ -427,7 +440,9 @@ class ListEntity(EndpointEntity):
|
||||||
for item in value:
|
for item in value:
|
||||||
child_obj = self._add_new_item()
|
child_obj = self._add_new_item()
|
||||||
child_obj.update_default_value(item)
|
child_obj.update_default_value(item)
|
||||||
child_obj.set_override_state(self._override_state)
|
child_obj.set_override_state(
|
||||||
|
self._override_state, self._ignore_missing_defaults
|
||||||
|
)
|
||||||
|
|
||||||
self._ignore_child_changes = False
|
self._ignore_child_changes = False
|
||||||
|
|
||||||
|
|
@ -460,7 +475,10 @@ class ListEntity(EndpointEntity):
|
||||||
child_obj.update_default_value(item)
|
child_obj.update_default_value(item)
|
||||||
if self._has_studio_override:
|
if self._has_studio_override:
|
||||||
child_obj.update_studio_value(item)
|
child_obj.update_studio_value(item)
|
||||||
child_obj.set_override_state(self._override_state)
|
child_obj.set_override_state(
|
||||||
|
self._override_state,
|
||||||
|
self._ignore_missing_defaults
|
||||||
|
)
|
||||||
|
|
||||||
self._ignore_child_changes = False
|
self._ignore_child_changes = False
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -217,7 +217,7 @@ class RootEntity(BaseItemEntity):
|
||||||
schema_data, *args, **kwargs
|
schema_data, *args, **kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
def set_override_state(self, state):
|
def set_override_state(self, state, ignore_missing_defaults=None):
|
||||||
"""Set override state and trigger it on children.
|
"""Set override state and trigger it on children.
|
||||||
|
|
||||||
Method will discard all changes in hierarchy and use values, metadata
|
Method will discard all changes in hierarchy and use values, metadata
|
||||||
|
|
@ -226,9 +226,12 @@ class RootEntity(BaseItemEntity):
|
||||||
Args:
|
Args:
|
||||||
state (OverrideState): State to which should be data changed.
|
state (OverrideState): State to which should be data changed.
|
||||||
"""
|
"""
|
||||||
|
if not ignore_missing_defaults:
|
||||||
|
ignore_missing_defaults = False
|
||||||
|
|
||||||
self._override_state = state
|
self._override_state = state
|
||||||
for child_obj in self.non_gui_children.values():
|
for child_obj in self.non_gui_children.values():
|
||||||
child_obj.set_override_state(state)
|
child_obj.set_override_state(state, ignore_missing_defaults)
|
||||||
|
|
||||||
def on_change(self):
|
def on_change(self):
|
||||||
"""Trigger callbacks on change."""
|
"""Trigger callbacks on change."""
|
||||||
|
|
|
||||||
|
|
@ -181,6 +181,103 @@
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## dict-conditional
|
||||||
|
- is similar to `dict` but has only one child entity that will be always available
|
||||||
|
- the one entity is enumerator of possible values and based on value of the entity are defined and used other children entities
|
||||||
|
- each value of enumerator have defined children that will be used
|
||||||
|
- there is no way how to have shared entities across multiple enum items
|
||||||
|
- value from enumerator is also stored next to other values
|
||||||
|
- to define the key under which will be enum value stored use `enum_key`
|
||||||
|
- `enum_key` must match key regex and any enum item can't have children with same key
|
||||||
|
- `enum_label` is label of the entity for UI purposes
|
||||||
|
- enum items are define with `enum_children`
|
||||||
|
- it's a list where each item represents enum item
|
||||||
|
- all items in `enum_children` must have at least `key` key which represents value stored under `enum_key`
|
||||||
|
- items can define `label` for UI purposes
|
||||||
|
- most important part is that item can define `children` key where are definitions of it's children (`children` value works the same way as in `dict`)
|
||||||
|
- entity must have defined `"label"` if is not used as widget
|
||||||
|
- is set as group if any parent is not group
|
||||||
|
- if `"label"` is entetered there which will be shown in GUI
|
||||||
|
- item with label can be collapsible
|
||||||
|
- that can be set with key `"collapsible"` as `True`/`False` (Default: `True`)
|
||||||
|
- with key `"collapsed"` as `True`/`False` can be set that is collapsed when GUI is opened (Default: `False`)
|
||||||
|
- it is possible to add darker background with `"highlight_content"` (Default: `False`)
|
||||||
|
- darker background has limits of maximum applies after 3-4 nested highlighted items there is not difference in the color
|
||||||
|
- output is dictionary `{the "key": children values}`
|
||||||
|
```
|
||||||
|
# Example
|
||||||
|
{
|
||||||
|
"type": "dict-conditional",
|
||||||
|
"key": "my_key",
|
||||||
|
"label": "My Key",
|
||||||
|
"enum_key": "type",
|
||||||
|
"enum_label": "label",
|
||||||
|
"enum_children": [
|
||||||
|
# Each item must be a dictionary with 'key'
|
||||||
|
{
|
||||||
|
"key": "action",
|
||||||
|
"label": "Action",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"key": "key",
|
||||||
|
"label": "Key"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"key": "label",
|
||||||
|
"label": "Label"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"key": "command",
|
||||||
|
"label": "Comand"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "menu",
|
||||||
|
"label": "Menu",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"key": "children",
|
||||||
|
"label": "Children",
|
||||||
|
"type": "list",
|
||||||
|
"object_type": "text"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
# Separator does not have children as "separator" value is enough
|
||||||
|
"key": "separator",
|
||||||
|
"label": "Separator"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
How output of the schema could look like on save:
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"type": "separator"
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
"type": "action",
|
||||||
|
"key": "action_1",
|
||||||
|
"label": "Action 1",
|
||||||
|
"command": "run command -arg"
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
"type": "menu",
|
||||||
|
"children": [
|
||||||
|
"child_1",
|
||||||
|
"child_2"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Inputs for setting any kind of value (`Pure` inputs)
|
## Inputs for setting any kind of value (`Pure` inputs)
|
||||||
- all these input must have defined `"key"` under which will be stored and `"label"` which will be shown next to input
|
- all these input must have defined `"key"` under which will be stored and `"label"` which will be shown next to input
|
||||||
- unless they are used in different types of inputs (later) "as widgets" in that case `"key"` and `"label"` are not required as there is not place where to set them
|
- unless they are used in different types of inputs (later) "as widgets" in that case `"key"` and `"label"` are not required as there is not place where to set them
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,54 @@
|
||||||
"label": "Color input",
|
"label": "Color input",
|
||||||
"type": "color"
|
"type": "color"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "dict-conditional",
|
||||||
|
"use_label_wrap": true,
|
||||||
|
"collapsible": true,
|
||||||
|
"key": "menu_items",
|
||||||
|
"label": "Menu items",
|
||||||
|
"enum_key": "type",
|
||||||
|
"enum_label": "Type",
|
||||||
|
"enum_children": [
|
||||||
|
{
|
||||||
|
"key": "action",
|
||||||
|
"label": "Action",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"key": "key",
|
||||||
|
"label": "Key"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"key": "label",
|
||||||
|
"label": "Label"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"key": "command",
|
||||||
|
"label": "Comand"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "menu",
|
||||||
|
"label": "Menu",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"key": "children",
|
||||||
|
"label": "Children",
|
||||||
|
"type": "list",
|
||||||
|
"object_type": "text"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "separator",
|
||||||
|
"label": "Separator"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "dict",
|
"type": "dict",
|
||||||
"key": "schema_template_exaples",
|
"key": "schema_template_exaples",
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ from openpype.settings.entities import (
|
||||||
GUIEntity,
|
GUIEntity,
|
||||||
DictImmutableKeysEntity,
|
DictImmutableKeysEntity,
|
||||||
DictMutableKeysEntity,
|
DictMutableKeysEntity,
|
||||||
|
DictConditionalEntity,
|
||||||
ListEntity,
|
ListEntity,
|
||||||
PathEntity,
|
PathEntity,
|
||||||
ListStrictEntity,
|
ListStrictEntity,
|
||||||
|
|
@ -35,6 +36,7 @@ from .base import GUIWidget
|
||||||
from .list_item_widget import ListWidget
|
from .list_item_widget import ListWidget
|
||||||
from .list_strict_widget import ListStrictWidget
|
from .list_strict_widget import ListStrictWidget
|
||||||
from .dict_mutable_widget import DictMutableKeysWidget
|
from .dict_mutable_widget import DictMutableKeysWidget
|
||||||
|
from .dict_conditional import DictConditionalWidget
|
||||||
from .item_widgets import (
|
from .item_widgets import (
|
||||||
BoolWidget,
|
BoolWidget,
|
||||||
DictImmutableKeysWidget,
|
DictImmutableKeysWidget,
|
||||||
|
|
@ -100,6 +102,9 @@ class SettingsCategoryWidget(QtWidgets.QWidget):
|
||||||
if isinstance(entity, GUIEntity):
|
if isinstance(entity, GUIEntity):
|
||||||
return GUIWidget(*args)
|
return GUIWidget(*args)
|
||||||
|
|
||||||
|
elif isinstance(entity, DictConditionalEntity):
|
||||||
|
return DictConditionalWidget(*args)
|
||||||
|
|
||||||
elif isinstance(entity, DictImmutableKeysEntity):
|
elif isinstance(entity, DictImmutableKeysEntity):
|
||||||
return DictImmutableKeysWidget(*args)
|
return DictImmutableKeysWidget(*args)
|
||||||
|
|
||||||
|
|
|
||||||
304
openpype/tools/settings/settings/dict_conditional.py
Normal file
304
openpype/tools/settings/settings/dict_conditional.py
Normal file
|
|
@ -0,0 +1,304 @@
|
||||||
|
from Qt import QtWidgets
|
||||||
|
|
||||||
|
from .widgets import (
|
||||||
|
ExpandingWidget,
|
||||||
|
GridLabelWidget
|
||||||
|
)
|
||||||
|
from .wrapper_widgets import (
|
||||||
|
WrapperWidget,
|
||||||
|
CollapsibleWrapper,
|
||||||
|
FormWrapper
|
||||||
|
)
|
||||||
|
from .base import BaseWidget
|
||||||
|
from openpype.tools.settings import CHILD_OFFSET
|
||||||
|
|
||||||
|
|
||||||
|
class DictConditionalWidget(BaseWidget):
|
||||||
|
def create_ui(self):
|
||||||
|
self.input_fields = []
|
||||||
|
|
||||||
|
self._content_by_enum_value = {}
|
||||||
|
self._last_enum_value = None
|
||||||
|
|
||||||
|
self.label_widget = None
|
||||||
|
self.body_widget = None
|
||||||
|
self.content_widget = None
|
||||||
|
self.content_layout = None
|
||||||
|
|
||||||
|
label = None
|
||||||
|
if self.entity.is_dynamic_item:
|
||||||
|
self._ui_as_dynamic_item()
|
||||||
|
|
||||||
|
elif self.entity.use_label_wrap:
|
||||||
|
self._ui_label_wrap()
|
||||||
|
|
||||||
|
else:
|
||||||
|
self._ui_item_base()
|
||||||
|
label = self.entity.label
|
||||||
|
|
||||||
|
self._parent_widget_by_entity_id = {}
|
||||||
|
self._enum_key_by_wrapper_id = {}
|
||||||
|
self._added_wrapper_ids = set()
|
||||||
|
|
||||||
|
self.content_layout.setColumnStretch(0, 0)
|
||||||
|
self.content_layout.setColumnStretch(1, 1)
|
||||||
|
|
||||||
|
# Add enum entity to layout mapping
|
||||||
|
enum_entity = self.entity.enum_entity
|
||||||
|
self._parent_widget_by_entity_id[enum_entity.id] = self.content_widget
|
||||||
|
|
||||||
|
# Add rest of entities to wrapper mappings
|
||||||
|
for enum_key, children in self.entity.gui_layout.items():
|
||||||
|
parent_widget_by_entity_id = {}
|
||||||
|
|
||||||
|
content_widget = QtWidgets.QWidget(self.content_widget)
|
||||||
|
content_layout = QtWidgets.QGridLayout(content_widget)
|
||||||
|
content_layout.setColumnStretch(0, 0)
|
||||||
|
content_layout.setColumnStretch(1, 1)
|
||||||
|
content_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
content_layout.setSpacing(5)
|
||||||
|
|
||||||
|
self._content_by_enum_value[enum_key] = {
|
||||||
|
"widget": content_widget,
|
||||||
|
"layout": content_layout
|
||||||
|
}
|
||||||
|
|
||||||
|
self._prepare_entity_layouts(
|
||||||
|
children,
|
||||||
|
content_widget,
|
||||||
|
parent_widget_by_entity_id
|
||||||
|
)
|
||||||
|
for item_id in parent_widget_by_entity_id.keys():
|
||||||
|
self._enum_key_by_wrapper_id[item_id] = enum_key
|
||||||
|
self._parent_widget_by_entity_id.update(parent_widget_by_entity_id)
|
||||||
|
|
||||||
|
enum_input_field = self.create_ui_for_entity(
|
||||||
|
self.category_widget, self.entity.enum_entity, self
|
||||||
|
)
|
||||||
|
self.enum_input_field = enum_input_field
|
||||||
|
self.input_fields.append(enum_input_field)
|
||||||
|
|
||||||
|
for item_key, children in self.entity.children.items():
|
||||||
|
content_widget = self._content_by_enum_value[item_key]["widget"]
|
||||||
|
row = self.content_layout.rowCount()
|
||||||
|
self.content_layout.addWidget(content_widget, row, 0, 1, 2)
|
||||||
|
|
||||||
|
for child_obj in children:
|
||||||
|
self.input_fields.append(
|
||||||
|
self.create_ui_for_entity(
|
||||||
|
self.category_widget, child_obj, self
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.entity.use_label_wrap and self.content_layout.count() == 0:
|
||||||
|
self.body_widget.hide_toolbox(True)
|
||||||
|
|
||||||
|
self.entity_widget.add_widget_to_layout(self, label)
|
||||||
|
|
||||||
|
def _prepare_entity_layouts(
|
||||||
|
self, gui_layout, widget, parent_widget_by_entity_id
|
||||||
|
):
|
||||||
|
for child in gui_layout:
|
||||||
|
if not isinstance(child, dict):
|
||||||
|
parent_widget_by_entity_id[child.id] = widget
|
||||||
|
continue
|
||||||
|
|
||||||
|
if child["type"] == "collapsible-wrap":
|
||||||
|
wrapper = CollapsibleWrapper(child, widget)
|
||||||
|
|
||||||
|
elif child["type"] == "form":
|
||||||
|
wrapper = FormWrapper(child, widget)
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise KeyError(
|
||||||
|
"Unknown Wrapper type \"{}\"".format(child["type"])
|
||||||
|
)
|
||||||
|
|
||||||
|
parent_widget_by_entity_id[wrapper.id] = widget
|
||||||
|
|
||||||
|
self._prepare_entity_layouts(
|
||||||
|
child["children"], wrapper, parent_widget_by_entity_id
|
||||||
|
)
|
||||||
|
|
||||||
|
def _ui_item_base(self):
|
||||||
|
self.setObjectName("DictInvisible")
|
||||||
|
|
||||||
|
self.content_widget = self
|
||||||
|
self.content_layout = QtWidgets.QGridLayout(self)
|
||||||
|
self.content_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.content_layout.setSpacing(5)
|
||||||
|
|
||||||
|
def _ui_as_dynamic_item(self):
|
||||||
|
content_widget = QtWidgets.QWidget(self)
|
||||||
|
content_widget.setObjectName("DictAsWidgetBody")
|
||||||
|
|
||||||
|
show_borders = str(int(self.entity.show_borders))
|
||||||
|
content_widget.setProperty("show_borders", show_borders)
|
||||||
|
|
||||||
|
label_widget = QtWidgets.QLabel(self.entity.label)
|
||||||
|
|
||||||
|
content_layout = QtWidgets.QGridLayout(content_widget)
|
||||||
|
content_layout.setContentsMargins(5, 5, 5, 5)
|
||||||
|
|
||||||
|
main_layout = QtWidgets.QHBoxLayout(self)
|
||||||
|
main_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
main_layout.setSpacing(5)
|
||||||
|
main_layout.addWidget(content_widget)
|
||||||
|
|
||||||
|
self.label_widget = label_widget
|
||||||
|
self.content_widget = content_widget
|
||||||
|
self.content_layout = content_layout
|
||||||
|
|
||||||
|
def _ui_label_wrap(self):
|
||||||
|
content_widget = QtWidgets.QWidget(self)
|
||||||
|
content_widget.setObjectName("ContentWidget")
|
||||||
|
|
||||||
|
if self.entity.highlight_content:
|
||||||
|
content_state = "hightlighted"
|
||||||
|
bottom_margin = 5
|
||||||
|
else:
|
||||||
|
content_state = ""
|
||||||
|
bottom_margin = 0
|
||||||
|
content_widget.setProperty("content_state", content_state)
|
||||||
|
content_layout_margins = (CHILD_OFFSET, 5, 0, bottom_margin)
|
||||||
|
|
||||||
|
body_widget = ExpandingWidget(self.entity.label, self)
|
||||||
|
label_widget = body_widget.label_widget
|
||||||
|
body_widget.set_content_widget(content_widget)
|
||||||
|
|
||||||
|
content_layout = QtWidgets.QGridLayout(content_widget)
|
||||||
|
content_layout.setContentsMargins(*content_layout_margins)
|
||||||
|
|
||||||
|
main_layout = QtWidgets.QHBoxLayout(self)
|
||||||
|
main_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
main_layout.setSpacing(0)
|
||||||
|
main_layout.addWidget(body_widget)
|
||||||
|
|
||||||
|
self.label_widget = label_widget
|
||||||
|
self.body_widget = body_widget
|
||||||
|
self.content_widget = content_widget
|
||||||
|
self.content_layout = content_layout
|
||||||
|
|
||||||
|
if self.entity.collapsible:
|
||||||
|
if not self.entity.collapsed:
|
||||||
|
body_widget.toggle_content()
|
||||||
|
else:
|
||||||
|
body_widget.hide_toolbox(hide_content=False)
|
||||||
|
|
||||||
|
def add_widget_to_layout(self, widget, label=None):
|
||||||
|
if not widget.entity:
|
||||||
|
map_id = widget.id
|
||||||
|
else:
|
||||||
|
map_id = widget.entity.id
|
||||||
|
|
||||||
|
content_widget = self.content_widget
|
||||||
|
content_layout = self.content_layout
|
||||||
|
if map_id != self.entity.enum_entity.id:
|
||||||
|
enum_value = self._enum_key_by_wrapper_id[map_id]
|
||||||
|
content_widget = self._content_by_enum_value[enum_value]["widget"]
|
||||||
|
content_layout = self._content_by_enum_value[enum_value]["layout"]
|
||||||
|
|
||||||
|
wrapper = self._parent_widget_by_entity_id[map_id]
|
||||||
|
if wrapper is not content_widget:
|
||||||
|
wrapper.add_widget_to_layout(widget, label)
|
||||||
|
if wrapper.id not in self._added_wrapper_ids:
|
||||||
|
self.add_widget_to_layout(wrapper)
|
||||||
|
self._added_wrapper_ids.add(wrapper.id)
|
||||||
|
return
|
||||||
|
|
||||||
|
row = content_layout.rowCount()
|
||||||
|
if not label or isinstance(widget, WrapperWidget):
|
||||||
|
content_layout.addWidget(widget, row, 0, 1, 2)
|
||||||
|
else:
|
||||||
|
label_widget = GridLabelWidget(label, widget)
|
||||||
|
label_widget.input_field = widget
|
||||||
|
widget.label_widget = label_widget
|
||||||
|
content_layout.addWidget(label_widget, row, 0, 1, 1)
|
||||||
|
content_layout.addWidget(widget, row, 1, 1, 1)
|
||||||
|
|
||||||
|
def set_entity_value(self):
|
||||||
|
for input_field in self.input_fields:
|
||||||
|
input_field.set_entity_value()
|
||||||
|
|
||||||
|
self._on_entity_change()
|
||||||
|
|
||||||
|
def hierarchical_style_update(self):
|
||||||
|
self.update_style()
|
||||||
|
for input_field in self.input_fields:
|
||||||
|
input_field.hierarchical_style_update()
|
||||||
|
|
||||||
|
def update_style(self):
|
||||||
|
if not self.body_widget and not self.label_widget:
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.entity.group_item:
|
||||||
|
group_item = self.entity.group_item
|
||||||
|
has_unsaved_changes = group_item.has_unsaved_changes
|
||||||
|
has_project_override = group_item.has_project_override
|
||||||
|
has_studio_override = group_item.has_studio_override
|
||||||
|
else:
|
||||||
|
has_unsaved_changes = self.entity.has_unsaved_changes
|
||||||
|
has_project_override = self.entity.has_project_override
|
||||||
|
has_studio_override = self.entity.has_studio_override
|
||||||
|
|
||||||
|
style_state = self.get_style_state(
|
||||||
|
self.is_invalid,
|
||||||
|
has_unsaved_changes,
|
||||||
|
has_project_override,
|
||||||
|
has_studio_override
|
||||||
|
)
|
||||||
|
if self._style_state == style_state:
|
||||||
|
return
|
||||||
|
|
||||||
|
self._style_state = style_state
|
||||||
|
|
||||||
|
if self.body_widget:
|
||||||
|
if style_state:
|
||||||
|
child_style_state = "child-{}".format(style_state)
|
||||||
|
else:
|
||||||
|
child_style_state = ""
|
||||||
|
|
||||||
|
self.body_widget.side_line_widget.setProperty(
|
||||||
|
"state", child_style_state
|
||||||
|
)
|
||||||
|
self.body_widget.side_line_widget.style().polish(
|
||||||
|
self.body_widget.side_line_widget
|
||||||
|
)
|
||||||
|
|
||||||
|
# There is nothing to care if there is no label
|
||||||
|
if not self.label_widget:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Don't change label if is not group or under group item
|
||||||
|
if not self.entity.is_group and not self.entity.group_item:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.label_widget.setProperty("state", style_state)
|
||||||
|
self.label_widget.style().polish(self.label_widget)
|
||||||
|
|
||||||
|
def _on_entity_change(self):
|
||||||
|
enum_value = self.enum_input_field.entity.value
|
||||||
|
if enum_value == self._last_enum_value:
|
||||||
|
return
|
||||||
|
|
||||||
|
self._last_enum_value = enum_value
|
||||||
|
for item_key, content in self._content_by_enum_value.items():
|
||||||
|
widget = content["widget"]
|
||||||
|
widget.setVisible(item_key == enum_value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_invalid(self):
|
||||||
|
return self._is_invalid or self._child_invalid
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _child_invalid(self):
|
||||||
|
for input_field in self.input_fields:
|
||||||
|
if input_field.is_invalid:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_invalid(self):
|
||||||
|
invalid = []
|
||||||
|
for input_field in self.input_fields:
|
||||||
|
invalid.extend(input_field.get_invalid())
|
||||||
|
return invalid
|
||||||
|
|
@ -145,7 +145,7 @@ class DictImmutableKeysWidget(BaseWidget):
|
||||||
self.content_widget = content_widget
|
self.content_widget = content_widget
|
||||||
self.content_layout = content_layout
|
self.content_layout = content_layout
|
||||||
|
|
||||||
if len(self.input_fields) == 1 and self.checkbox_widget:
|
if len(self.input_fields) == 1 and self.checkbox_child:
|
||||||
body_widget.hide_toolbox(hide_content=True)
|
body_widget.hide_toolbox(hide_content=True)
|
||||||
|
|
||||||
elif self.entity.collapsible:
|
elif self.entity.collapsible:
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,13 @@ class Window(QtWidgets.QDialog):
|
||||||
self._db = AvalonMongoDB()
|
self._db = AvalonMongoDB()
|
||||||
self._db.install()
|
self._db.install()
|
||||||
|
|
||||||
|
try:
|
||||||
|
settings = QtCore.QSettings("pypeclub", "StandalonePublisher")
|
||||||
|
except Exception:
|
||||||
|
settings = None
|
||||||
|
|
||||||
|
self._settings = settings
|
||||||
|
|
||||||
self.pyblish_paths = pyblish_paths
|
self.pyblish_paths = pyblish_paths
|
||||||
|
|
||||||
self.setWindowTitle("Standalone Publish")
|
self.setWindowTitle("Standalone Publish")
|
||||||
|
|
@ -44,7 +51,7 @@ class Window(QtWidgets.QDialog):
|
||||||
self.valid_parent = False
|
self.valid_parent = False
|
||||||
|
|
||||||
# assets widget
|
# assets widget
|
||||||
widget_assets = AssetWidget(dbcon=self._db, parent=self)
|
widget_assets = AssetWidget(self._db, settings, self)
|
||||||
|
|
||||||
# family widget
|
# family widget
|
||||||
widget_family = FamilyWidget(dbcon=self._db, parent=self)
|
widget_family = FamilyWidget(dbcon=self._db, parent=self)
|
||||||
|
|
|
||||||
|
|
@ -127,11 +127,12 @@ class AssetWidget(QtWidgets.QWidget):
|
||||||
current_changed = QtCore.Signal() # on view current index change
|
current_changed = QtCore.Signal() # on view current index change
|
||||||
task_changed = QtCore.Signal()
|
task_changed = QtCore.Signal()
|
||||||
|
|
||||||
def __init__(self, dbcon, parent=None):
|
def __init__(self, dbcon, settings, parent=None):
|
||||||
super(AssetWidget, self).__init__(parent=parent)
|
super(AssetWidget, self).__init__(parent=parent)
|
||||||
self.setContentsMargins(0, 0, 0, 0)
|
self.setContentsMargins(0, 0, 0, 0)
|
||||||
|
|
||||||
self.dbcon = dbcon
|
self.dbcon = dbcon
|
||||||
|
self._settings = settings
|
||||||
|
|
||||||
layout = QtWidgets.QVBoxLayout()
|
layout = QtWidgets.QVBoxLayout()
|
||||||
layout.setContentsMargins(0, 0, 0, 0)
|
layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
|
@ -139,6 +140,10 @@ class AssetWidget(QtWidgets.QWidget):
|
||||||
|
|
||||||
# Project
|
# Project
|
||||||
self.combo_projects = QtWidgets.QComboBox()
|
self.combo_projects = QtWidgets.QComboBox()
|
||||||
|
# Change delegate so stylysheets are applied
|
||||||
|
project_delegate = QtWidgets.QStyledItemDelegate(self.combo_projects)
|
||||||
|
self.combo_projects.setItemDelegate(project_delegate)
|
||||||
|
|
||||||
self._set_projects()
|
self._set_projects()
|
||||||
self.combo_projects.currentTextChanged.connect(self.on_project_change)
|
self.combo_projects.currentTextChanged.connect(self.on_project_change)
|
||||||
# Tree View
|
# Tree View
|
||||||
|
|
@ -198,6 +203,7 @@ class AssetWidget(QtWidgets.QWidget):
|
||||||
|
|
||||||
self.selection_changed.connect(self._refresh_tasks)
|
self.selection_changed.connect(self._refresh_tasks)
|
||||||
|
|
||||||
|
self.project_delegate = project_delegate
|
||||||
self.task_view = task_view
|
self.task_view = task_view
|
||||||
self.task_model = task_model
|
self.task_model = task_model
|
||||||
self.refreshButton = refresh
|
self.refreshButton = refresh
|
||||||
|
|
@ -237,15 +243,59 @@ class AssetWidget(QtWidgets.QWidget):
|
||||||
output.extend(self.get_parents(parent))
|
output.extend(self.get_parents(parent))
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
def _get_last_projects(self):
|
||||||
|
if not self._settings:
|
||||||
|
return []
|
||||||
|
|
||||||
|
project_names = []
|
||||||
|
for project_name in self._settings.value("projects", "").split("|"):
|
||||||
|
if project_name:
|
||||||
|
project_names.append(project_name)
|
||||||
|
return project_names
|
||||||
|
|
||||||
|
def _add_last_project(self, project_name):
|
||||||
|
if not self._settings:
|
||||||
|
return
|
||||||
|
|
||||||
|
last_projects = []
|
||||||
|
for _project_name in self._settings.value("projects", "").split("|"):
|
||||||
|
if _project_name:
|
||||||
|
last_projects.append(_project_name)
|
||||||
|
|
||||||
|
if project_name in last_projects:
|
||||||
|
last_projects.remove(project_name)
|
||||||
|
|
||||||
|
last_projects.insert(0, project_name)
|
||||||
|
while len(last_projects) > 5:
|
||||||
|
last_projects.pop(-1)
|
||||||
|
|
||||||
|
self._settings.setValue("projects", "|".join(last_projects))
|
||||||
|
|
||||||
def _set_projects(self):
|
def _set_projects(self):
|
||||||
projects = list()
|
project_names = list()
|
||||||
for project in self.dbcon.projects():
|
for project in self.dbcon.projects():
|
||||||
projects.append(project['name'])
|
project_name = project.get("name")
|
||||||
|
if project_name:
|
||||||
|
project_names.append(project_name)
|
||||||
|
|
||||||
self.combo_projects.clear()
|
self.combo_projects.clear()
|
||||||
if len(projects) > 0:
|
|
||||||
self.combo_projects.addItems(projects)
|
if not project_names:
|
||||||
self.dbcon.Session["AVALON_PROJECT"] = projects[0]
|
return
|
||||||
|
|
||||||
|
sorted_project_names = list(sorted(project_names))
|
||||||
|
self.combo_projects.addItems(list(sorted(sorted_project_names)))
|
||||||
|
|
||||||
|
last_project = sorted_project_names[0]
|
||||||
|
for project_name in self._get_last_projects():
|
||||||
|
if project_name in sorted_project_names:
|
||||||
|
last_project = project_name
|
||||||
|
break
|
||||||
|
|
||||||
|
index = sorted_project_names.index(last_project)
|
||||||
|
self.combo_projects.setCurrentIndex(index)
|
||||||
|
|
||||||
|
self.dbcon.Session["AVALON_PROJECT"] = last_project
|
||||||
|
|
||||||
def on_project_change(self):
|
def on_project_change(self):
|
||||||
projects = list()
|
projects = list()
|
||||||
|
|
@ -254,6 +304,7 @@ class AssetWidget(QtWidgets.QWidget):
|
||||||
project_name = self.combo_projects.currentText()
|
project_name = self.combo_projects.currentText()
|
||||||
if project_name in projects:
|
if project_name in projects:
|
||||||
self.dbcon.Session["AVALON_PROJECT"] = project_name
|
self.dbcon.Session["AVALON_PROJECT"] = project_name
|
||||||
|
self._add_last_project(project_name)
|
||||||
|
|
||||||
self.project_changed.emit(project_name)
|
self.project_changed.emit(project_name)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""Package declaring Pype version."""
|
"""Package declaring Pype version."""
|
||||||
__version__ = "3.2.0-nightly.6"
|
__version__ = "3.2.0-nightly.7"
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,8 @@ function Show-PSWarning() {
|
||||||
function Install-Poetry() {
|
function Install-Poetry() {
|
||||||
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
||||||
Write-Host "Installing Poetry ... "
|
Write-Host "Installing Poetry ... "
|
||||||
(Invoke-WebRequest -Uri https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py -UseBasicParsing).Content | python -
|
$env:POETRY_HOME="$openpype_root\.poetry"
|
||||||
|
(Invoke-WebRequest -Uri https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py -UseBasicParsing).Content | python -
|
||||||
}
|
}
|
||||||
|
|
||||||
$art = @"
|
$art = @"
|
||||||
|
|
@ -115,11 +116,9 @@ $openpype_root = (Get-Item $script_dir).parent.FullName
|
||||||
|
|
||||||
$env:_INSIDE_OPENPYPE_TOOL = "1"
|
$env:_INSIDE_OPENPYPE_TOOL = "1"
|
||||||
|
|
||||||
# make sure Poetry is in PATH
|
|
||||||
if (-not (Test-Path 'env:POETRY_HOME')) {
|
if (-not (Test-Path 'env:POETRY_HOME')) {
|
||||||
$env:POETRY_HOME = "$openpype_root\.poetry"
|
$env:POETRY_HOME = "$openpype_root\.poetry"
|
||||||
}
|
}
|
||||||
$env:PATH = "$($env:PATH);$($env:POETRY_HOME)\bin"
|
|
||||||
|
|
||||||
Set-Location -Path $openpype_root
|
Set-Location -Path $openpype_root
|
||||||
|
|
||||||
|
|
@ -164,7 +163,7 @@ Write-Host " ]" -ForegroundColor white
|
||||||
|
|
||||||
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
||||||
Write-Host "Reading Poetry ... " -NoNewline
|
Write-Host "Reading Poetry ... " -NoNewline
|
||||||
if (-not (Test-Path -PathType Container -Path "$openpype_root\.poetry\bin")) {
|
if (-not (Test-Path -PathType Container -Path "$($env:POETRY_HOME)\bin")) {
|
||||||
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
||||||
Write-Host "*** " -NoNewline -ForegroundColor Yellow
|
Write-Host "*** " -NoNewline -ForegroundColor Yellow
|
||||||
Write-Host "We need to install Poetry create virtual env first ..."
|
Write-Host "We need to install Poetry create virtual env first ..."
|
||||||
|
|
@ -184,7 +183,7 @@ Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||||
Write-Host "Building OpenPype ..."
|
Write-Host "Building OpenPype ..."
|
||||||
$startTime = [int][double]::Parse((Get-Date -UFormat %s))
|
$startTime = [int][double]::Parse((Get-Date -UFormat %s))
|
||||||
|
|
||||||
$out = & poetry run python setup.py build 2>&1
|
$out = & "$($env:POETRY_HOME)\bin\poetry" run python setup.py build 2>&1
|
||||||
Set-Content -Path "$($openpype_root)\build\build.log" -Value $out
|
Set-Content -Path "$($openpype_root)\build\build.log" -Value $out
|
||||||
if ($LASTEXITCODE -ne 0)
|
if ($LASTEXITCODE -ne 0)
|
||||||
{
|
{
|
||||||
|
|
@ -195,7 +194,7 @@ if ($LASTEXITCODE -ne 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
Set-Content -Path "$($openpype_root)\build\build.log" -Value $out
|
Set-Content -Path "$($openpype_root)\build\build.log" -Value $out
|
||||||
& poetry run python "$($openpype_root)\tools\build_dependencies.py"
|
& "$($env:POETRY_HOME)\bin\poetry" run python "$($openpype_root)\tools\build_dependencies.py"
|
||||||
|
|
||||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||||
Write-Host "restoring current directory"
|
Write-Host "restoring current directory"
|
||||||
|
|
|
||||||
|
|
@ -140,21 +140,6 @@ realpath () {
|
||||||
echo $(cd $(dirname "$1") || return; pwd)/$(basename "$1")
|
echo $(cd $(dirname "$1") || return; pwd)/$(basename "$1")
|
||||||
}
|
}
|
||||||
|
|
||||||
##############################################################################
|
|
||||||
# Install Poetry when needed
|
|
||||||
# Globals:
|
|
||||||
# PATH
|
|
||||||
# Arguments:
|
|
||||||
# None
|
|
||||||
# Returns:
|
|
||||||
# None
|
|
||||||
###############################################################################
|
|
||||||
install_poetry () {
|
|
||||||
echo -e "${BIGreen}>>>${RST} Installing Poetry ..."
|
|
||||||
command -v curl >/dev/null 2>&1 || { echo -e "${BIRed}!!!${RST}${BIYellow} Missing ${RST}${BIBlue}curl${BIYellow} command.${RST}"; return 1; }
|
|
||||||
curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python -
|
|
||||||
}
|
|
||||||
|
|
||||||
# Main
|
# Main
|
||||||
main () {
|
main () {
|
||||||
echo -e "${BGreen}"
|
echo -e "${BGreen}"
|
||||||
|
|
@ -171,11 +156,9 @@ main () {
|
||||||
|
|
||||||
_inside_openpype_tool="1"
|
_inside_openpype_tool="1"
|
||||||
|
|
||||||
# make sure Poetry is in PATH
|
|
||||||
if [[ -z $POETRY_HOME ]]; then
|
if [[ -z $POETRY_HOME ]]; then
|
||||||
export POETRY_HOME="$openpype_root/.poetry"
|
export POETRY_HOME="$openpype_root/.poetry"
|
||||||
fi
|
fi
|
||||||
export PATH="$POETRY_HOME/bin:$PATH"
|
|
||||||
|
|
||||||
echo -e "${BIYellow}---${RST} Cleaning build directory ..."
|
echo -e "${BIYellow}---${RST} Cleaning build directory ..."
|
||||||
rm -rf "$openpype_root/build" && mkdir "$openpype_root/build" > /dev/null
|
rm -rf "$openpype_root/build" && mkdir "$openpype_root/build" > /dev/null
|
||||||
|
|
@ -201,11 +184,11 @@ if [ "$disable_submodule_update" == 1 ]; then
|
||||||
fi
|
fi
|
||||||
echo -e "${BIGreen}>>>${RST} Building ..."
|
echo -e "${BIGreen}>>>${RST} Building ..."
|
||||||
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
||||||
poetry run python "$openpype_root/setup.py" build > "$openpype_root/build/build.log" || { echo -e "${BIRed}!!!${RST} Build failed, see the build log."; return; }
|
"$POETRY_HOME/bin/poetry" run python "$openpype_root/setup.py" build > "$openpype_root/build/build.log" || { echo -e "${BIRed}!!!${RST} Build failed, see the build log."; return; }
|
||||||
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||||
poetry run python "$openpype_root/setup.py" bdist_mac > "$openpype_root/build/build.log" || { echo -e "${BIRed}!!!${RST} Build failed, see the build log."; return; }
|
"$POETRY_HOME/bin/poetry" run python "$openpype_root/setup.py" bdist_mac > "$openpype_root/build/build.log" || { echo -e "${BIRed}!!!${RST} Build failed, see the build log."; return; }
|
||||||
fi
|
fi
|
||||||
poetry run python "$openpype_root/tools/build_dependencies.py"
|
"$POETRY_HOME/bin/poetry" run python "$openpype_root/tools/build_dependencies.py"
|
||||||
|
|
||||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||||
# fix code signing issue
|
# fix code signing issue
|
||||||
|
|
|
||||||
|
|
@ -64,14 +64,6 @@ function Show-PSWarning() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Install-Poetry() {
|
|
||||||
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
|
||||||
Write-Host "Installing Poetry ... "
|
|
||||||
(Invoke-WebRequest -Uri https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py -UseBasicParsing).Content | python -
|
|
||||||
# add it to PATH
|
|
||||||
$env:PATH = "$($env:PATH);$($env:USERPROFILE)\.poetry\bin"
|
|
||||||
}
|
|
||||||
|
|
||||||
$art = @"
|
$art = @"
|
||||||
|
|
||||||
. . .. . ..
|
. . .. . ..
|
||||||
|
|
|
||||||
|
|
@ -49,9 +49,7 @@ function Install-Poetry() {
|
||||||
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
||||||
Write-Host "Installing Poetry ... "
|
Write-Host "Installing Poetry ... "
|
||||||
$env:POETRY_HOME="$openpype_root\.poetry"
|
$env:POETRY_HOME="$openpype_root\.poetry"
|
||||||
(Invoke-WebRequest -Uri https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py -UseBasicParsing).Content | python -
|
(Invoke-WebRequest -Uri https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py -UseBasicParsing).Content | python -
|
||||||
# add it to PATH
|
|
||||||
$env:PATH = "$($env:PATH);$openpype_root\.poetry\bin"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -94,11 +92,10 @@ $current_dir = Get-Location
|
||||||
$script_dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
|
$script_dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
|
||||||
$openpype_root = (Get-Item $script_dir).parent.FullName
|
$openpype_root = (Get-Item $script_dir).parent.FullName
|
||||||
|
|
||||||
# make sure Poetry is in PATH
|
|
||||||
if (-not (Test-Path 'env:POETRY_HOME')) {
|
if (-not (Test-Path 'env:POETRY_HOME')) {
|
||||||
$env:POETRY_HOME = "$openpype_root\.poetry"
|
$env:POETRY_HOME = "$openpype_root\.poetry"
|
||||||
}
|
}
|
||||||
$env:PATH = "$($env:PATH);$($env:POETRY_HOME)\bin"
|
|
||||||
|
|
||||||
Set-Location -Path $openpype_root
|
Set-Location -Path $openpype_root
|
||||||
|
|
||||||
|
|
@ -145,7 +142,7 @@ Test-Python
|
||||||
|
|
||||||
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
||||||
Write-Host "Reading Poetry ... " -NoNewline
|
Write-Host "Reading Poetry ... " -NoNewline
|
||||||
if (-not (Test-Path -PathType Container -Path "$openpype_root\.poetry\bin")) {
|
if (-not (Test-Path -PathType Container -Path "$($env:POETRY_HOME)\bin")) {
|
||||||
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
||||||
Install-Poetry
|
Install-Poetry
|
||||||
Write-Host "INSTALLED" -ForegroundColor Cyan
|
Write-Host "INSTALLED" -ForegroundColor Cyan
|
||||||
|
|
@ -160,7 +157,7 @@ if (-not (Test-Path -PathType Leaf -Path "$($openpype_root)\poetry.lock")) {
|
||||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||||
Write-Host "Installing virtual environment from lock."
|
Write-Host "Installing virtual environment from lock."
|
||||||
}
|
}
|
||||||
& poetry install --no-root $poetry_verbosity
|
& "$env:POETRY_HOME\bin\poetry" install --no-root $poetry_verbosity --ansi
|
||||||
if ($LASTEXITCODE -ne 0) {
|
if ($LASTEXITCODE -ne 0) {
|
||||||
Write-Host "!!! " -ForegroundColor yellow -NoNewline
|
Write-Host "!!! " -ForegroundColor yellow -NoNewline
|
||||||
Write-Host "Poetry command failed."
|
Write-Host "Poetry command failed."
|
||||||
|
|
|
||||||
|
|
@ -109,8 +109,7 @@ install_poetry () {
|
||||||
echo -e "${BIGreen}>>>${RST} Installing Poetry ..."
|
echo -e "${BIGreen}>>>${RST} Installing Poetry ..."
|
||||||
export POETRY_HOME="$openpype_root/.poetry"
|
export POETRY_HOME="$openpype_root/.poetry"
|
||||||
command -v curl >/dev/null 2>&1 || { echo -e "${BIRed}!!!${RST}${BIYellow} Missing ${RST}${BIBlue}curl${BIYellow} command.${RST}"; return 1; }
|
command -v curl >/dev/null 2>&1 || { echo -e "${BIRed}!!!${RST}${BIYellow} Missing ${RST}${BIBlue}curl${BIYellow} command.${RST}"; return 1; }
|
||||||
curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python -
|
curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py | python -
|
||||||
export PATH="$PATH:$POETRY_HOME/bin"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
@ -154,11 +153,10 @@ main () {
|
||||||
|
|
||||||
# Directories
|
# Directories
|
||||||
openpype_root=$(realpath $(dirname $(dirname "${BASH_SOURCE[0]}")))
|
openpype_root=$(realpath $(dirname $(dirname "${BASH_SOURCE[0]}")))
|
||||||
# make sure Poetry is in PATH
|
|
||||||
if [[ -z $POETRY_HOME ]]; then
|
if [[ -z $POETRY_HOME ]]; then
|
||||||
export POETRY_HOME="$openpype_root/.poetry"
|
export POETRY_HOME="$openpype_root/.poetry"
|
||||||
fi
|
fi
|
||||||
export PATH="$POETRY_HOME/bin:$PATH"
|
|
||||||
|
|
||||||
|
|
||||||
pushd "$openpype_root" > /dev/null || return > /dev/null
|
pushd "$openpype_root" > /dev/null || return > /dev/null
|
||||||
|
|
@ -177,7 +175,7 @@ main () {
|
||||||
echo -e "${BIGreen}>>>${RST} Installing dependencies ..."
|
echo -e "${BIGreen}>>>${RST} Installing dependencies ..."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
poetry install --no-root $poetry_verbosity || { echo -e "${BIRed}!!!${RST} Poetry environment installation failed"; return; }
|
"$POETRY_HOME/bin/poetry" install --no-root $poetry_verbosity || { echo -e "${BIRed}!!!${RST} Poetry environment installation failed"; return; }
|
||||||
|
|
||||||
echo -e "${BIGreen}>>>${RST} Cleaning cache files ..."
|
echo -e "${BIGreen}>>>${RST} Cleaning cache files ..."
|
||||||
clean_pyc
|
clean_pyc
|
||||||
|
|
@ -186,10 +184,10 @@ main () {
|
||||||
# cx_freeze will crash on missing __pychache__ on these but
|
# cx_freeze will crash on missing __pychache__ on these but
|
||||||
# reinstalling them solves the problem.
|
# reinstalling them solves the problem.
|
||||||
echo -e "${BIGreen}>>>${RST} Fixing pycache bug ..."
|
echo -e "${BIGreen}>>>${RST} Fixing pycache bug ..."
|
||||||
poetry run python -m pip install --force-reinstall pip
|
"$POETRY_HOME/bin/poetry" run python -m pip install --force-reinstall pip
|
||||||
poetry run pip install --force-reinstall setuptools
|
"$POETRY_HOME/bin/poetry" run pip install --force-reinstall setuptools
|
||||||
poetry run pip install --force-reinstall wheel
|
"$POETRY_HOME/bin/poetry" run pip install --force-reinstall wheel
|
||||||
poetry run python -m pip install --force-reinstall pip
|
"$POETRY_HOME/bin/poetry" run python -m pip install --force-reinstall pip
|
||||||
}
|
}
|
||||||
|
|
||||||
main -3
|
main -3
|
||||||
|
|
|
||||||
|
|
@ -45,11 +45,9 @@ $openpype_root = (Get-Item $script_dir).parent.FullName
|
||||||
|
|
||||||
$env:_INSIDE_OPENPYPE_TOOL = "1"
|
$env:_INSIDE_OPENPYPE_TOOL = "1"
|
||||||
|
|
||||||
# make sure Poetry is in PATH
|
|
||||||
if (-not (Test-Path 'env:POETRY_HOME')) {
|
if (-not (Test-Path 'env:POETRY_HOME')) {
|
||||||
$env:POETRY_HOME = "$openpype_root\.poetry"
|
$env:POETRY_HOME = "$openpype_root\.poetry"
|
||||||
}
|
}
|
||||||
$env:PATH = "$($env:PATH);$($env:POETRY_HOME)\bin"
|
|
||||||
|
|
||||||
Set-Location -Path $openpype_root
|
Set-Location -Path $openpype_root
|
||||||
|
|
||||||
|
|
@ -87,7 +85,7 @@ if (-not $openpype_version) {
|
||||||
|
|
||||||
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
||||||
Write-Host "Reading Poetry ... " -NoNewline
|
Write-Host "Reading Poetry ... " -NoNewline
|
||||||
if (-not (Test-Path -PathType Container -Path "$openpype_root\.poetry\bin")) {
|
if (-not (Test-Path -PathType Container -Path "$($env:POETRY_HOME)\bin")) {
|
||||||
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
||||||
Write-Host "*** " -NoNewline -ForegroundColor Yellow
|
Write-Host "*** " -NoNewline -ForegroundColor Yellow
|
||||||
Write-Host "We need to install Poetry create virtual env first ..."
|
Write-Host "We need to install Poetry create virtual env first ..."
|
||||||
|
|
@ -107,5 +105,5 @@ Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||||
Write-Host "Generating zip from current sources ..."
|
Write-Host "Generating zip from current sources ..."
|
||||||
$env:PYTHONPATH="$($openpype_root);$($env:PYTHONPATH)"
|
$env:PYTHONPATH="$($openpype_root);$($env:PYTHONPATH)"
|
||||||
$env:OPENPYPE_ROOT="$($openpype_root)"
|
$env:OPENPYPE_ROOT="$($openpype_root)"
|
||||||
& poetry run python "$($openpype_root)\tools\create_zip.py" $ARGS
|
& "$($env:POETRY_HOME)\bin\poetry" run python "$($openpype_root)\tools\create_zip.py" $ARGS
|
||||||
Set-Location -Path $current_dir
|
Set-Location -Path $current_dir
|
||||||
|
|
|
||||||
|
|
@ -114,11 +114,9 @@ main () {
|
||||||
|
|
||||||
_inside_openpype_tool="1"
|
_inside_openpype_tool="1"
|
||||||
|
|
||||||
# make sure Poetry is in PATH
|
|
||||||
if [[ -z $POETRY_HOME ]]; then
|
if [[ -z $POETRY_HOME ]]; then
|
||||||
export POETRY_HOME="$openpype_root/.poetry"
|
export POETRY_HOME="$openpype_root/.poetry"
|
||||||
fi
|
fi
|
||||||
export PATH="$POETRY_HOME/bin:$PATH"
|
|
||||||
|
|
||||||
pushd "$openpype_root" > /dev/null || return > /dev/null
|
pushd "$openpype_root" > /dev/null || return > /dev/null
|
||||||
|
|
||||||
|
|
@ -134,7 +132,7 @@ main () {
|
||||||
echo -e "${BIGreen}>>>${RST} Generating zip from current sources ..."
|
echo -e "${BIGreen}>>>${RST} Generating zip from current sources ..."
|
||||||
PYTHONPATH="$openpype_root:$PYTHONPATH"
|
PYTHONPATH="$openpype_root:$PYTHONPATH"
|
||||||
OPENPYPE_ROOT="$openpype_root"
|
OPENPYPE_ROOT="$openpype_root"
|
||||||
poetry run python3 "$openpype_root/tools/create_zip.py" "$@"
|
"$POETRY_HOME/bin/poetry" run python3 "$openpype_root/tools/create_zip.py" "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|
|
||||||
|
|
@ -17,18 +17,15 @@ $openpype_root = (Get-Item $script_dir).parent.FullName
|
||||||
|
|
||||||
$env:_INSIDE_OPENPYPE_TOOL = "1"
|
$env:_INSIDE_OPENPYPE_TOOL = "1"
|
||||||
|
|
||||||
# make sure Poetry is in PATH
|
|
||||||
if (-not (Test-Path 'env:POETRY_HOME')) {
|
if (-not (Test-Path 'env:POETRY_HOME')) {
|
||||||
$env:POETRY_HOME = "$openpype_root\.poetry"
|
$env:POETRY_HOME = "$openpype_root\.poetry"
|
||||||
}
|
}
|
||||||
$env:PATH = "$($env:PATH);$($env:POETRY_HOME)\bin"
|
|
||||||
|
|
||||||
Set-Location -Path $openpype_root
|
Set-Location -Path $openpype_root
|
||||||
|
|
||||||
|
|
||||||
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
||||||
Write-Host "Reading Poetry ... " -NoNewline
|
Write-Host "Reading Poetry ... " -NoNewline
|
||||||
if (-not (Test-Path -PathType Container -Path "$openpype_root\.poetry\bin")) {
|
if (-not (Test-Path -PathType Container -Path "$($env:POETRY_HOME)\bin")) {
|
||||||
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
||||||
Write-Host "*** " -NoNewline -ForegroundColor Yellow
|
Write-Host "*** " -NoNewline -ForegroundColor Yellow
|
||||||
Write-Host "We need to install Poetry create virtual env first ..."
|
Write-Host "We need to install Poetry create virtual env first ..."
|
||||||
|
|
@ -37,5 +34,5 @@ if (-not (Test-Path -PathType Container -Path "$openpype_root\.poetry\bin")) {
|
||||||
Write-Host "OK" -ForegroundColor Green
|
Write-Host "OK" -ForegroundColor Green
|
||||||
}
|
}
|
||||||
|
|
||||||
& poetry run python "$($openpype_root)\tools\fetch_thirdparty_libs.py"
|
& "$($env:POETRY_HOME)\bin\poetry" run python "$($openpype_root)\tools\fetch_thirdparty_libs.py"
|
||||||
Set-Location -Path $current_dir
|
Set-Location -Path $current_dir
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# Run Pype Tray
|
|
||||||
|
|
||||||
|
|
||||||
art () {
|
art () {
|
||||||
cat <<-EOF
|
cat <<-EOF
|
||||||
|
|
||||||
|
|
@ -82,11 +79,9 @@ main () {
|
||||||
|
|
||||||
_inside_openpype_tool="1"
|
_inside_openpype_tool="1"
|
||||||
|
|
||||||
# make sure Poetry is in PATH
|
|
||||||
if [[ -z $POETRY_HOME ]]; then
|
if [[ -z $POETRY_HOME ]]; then
|
||||||
export POETRY_HOME="$openpype_root/.poetry"
|
export POETRY_HOME="$openpype_root/.poetry"
|
||||||
fi
|
fi
|
||||||
export PATH="$POETRY_HOME/bin:$PATH"
|
|
||||||
|
|
||||||
echo -e "${BIGreen}>>>${RST} Reading Poetry ... \c"
|
echo -e "${BIGreen}>>>${RST} Reading Poetry ... \c"
|
||||||
if [ -f "$POETRY_HOME/bin/poetry" ]; then
|
if [ -f "$POETRY_HOME/bin/poetry" ]; then
|
||||||
|
|
@ -100,7 +95,7 @@ main () {
|
||||||
pushd "$openpype_root" > /dev/null || return > /dev/null
|
pushd "$openpype_root" > /dev/null || return > /dev/null
|
||||||
|
|
||||||
echo -e "${BIGreen}>>>${RST} Running Pype tool ..."
|
echo -e "${BIGreen}>>>${RST} Running Pype tool ..."
|
||||||
poetry run python "$openpype_root/tools/fetch_thirdparty_libs.py"
|
"$POETRY_HOME/bin/poetry" run python "$openpype_root/tools/fetch_thirdparty_libs.py"
|
||||||
}
|
}
|
||||||
|
|
||||||
main
|
main
|
||||||
|
|
@ -19,11 +19,9 @@ $openpype_root = (Get-Item $script_dir).parent.FullName
|
||||||
|
|
||||||
$env:_INSIDE_OPENPYPE_TOOL = "1"
|
$env:_INSIDE_OPENPYPE_TOOL = "1"
|
||||||
|
|
||||||
# make sure Poetry is in PATH
|
|
||||||
if (-not (Test-Path 'env:POETRY_HOME')) {
|
if (-not (Test-Path 'env:POETRY_HOME')) {
|
||||||
$env:POETRY_HOME = "$openpype_root\.poetry"
|
$env:POETRY_HOME = "$openpype_root\.poetry"
|
||||||
}
|
}
|
||||||
$env:PATH = "$($env:PATH);$($env:POETRY_HOME)\bin"
|
|
||||||
|
|
||||||
Set-Location -Path $openpype_root
|
Set-Location -Path $openpype_root
|
||||||
|
|
||||||
|
|
@ -50,7 +48,7 @@ Write-Host $art -ForegroundColor DarkGreen
|
||||||
|
|
||||||
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
||||||
Write-Host "Reading Poetry ... " -NoNewline
|
Write-Host "Reading Poetry ... " -NoNewline
|
||||||
if (-not (Test-Path -PathType Container -Path "$openpype_root\.poetry\bin")) {
|
if (-not (Test-Path -PathType Container -Path "$($env:POETRY_HOME)\bin")) {
|
||||||
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
||||||
Write-Host "*** " -NoNewline -ForegroundColor Yellow
|
Write-Host "*** " -NoNewline -ForegroundColor Yellow
|
||||||
Write-Host "We need to install Poetry create virtual env first ..."
|
Write-Host "We need to install Poetry create virtual env first ..."
|
||||||
|
|
@ -63,10 +61,10 @@ Write-Host "This will not overwrite existing source rst files, only scan and add
|
||||||
Set-Location -Path $openpype_root
|
Set-Location -Path $openpype_root
|
||||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||||
Write-Host "Running apidoc ..."
|
Write-Host "Running apidoc ..."
|
||||||
& poetry run sphinx-apidoc -M -e -d 10 --ext-intersphinx --ext-todo --ext-coverage --ext-viewcode -o "$($openpype_root)\docs\source" igniter
|
& "$env:POETRY_HOME\bin\poetry" run sphinx-apidoc -M -e -d 10 --ext-intersphinx --ext-todo --ext-coverage --ext-viewcode -o "$($openpype_root)\docs\source" igniter
|
||||||
& poetry run sphinx-apidoc.exe -M -e -d 10 --ext-intersphinx --ext-todo --ext-coverage --ext-viewcode -o "$($openpype_root)\docs\source" openpype vendor, openpype\vendor
|
& "$env:POETRY_HOME\bin\poetry" run sphinx-apidoc.exe -M -e -d 10 --ext-intersphinx --ext-todo --ext-coverage --ext-viewcode -o "$($openpype_root)\docs\source" openpype vendor, openpype\vendor
|
||||||
|
|
||||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||||
Write-Host "Building html ..."
|
Write-Host "Building html ..."
|
||||||
& poetry run python "$($openpype_root)\setup.py" build_sphinx
|
& "$env:POETRY_HOME\bin\poetry" run python "$($openpype_root)\setup.py" build_sphinx
|
||||||
Set-Location -Path $current_dir
|
Set-Location -Path $current_dir
|
||||||
|
|
|
||||||
|
|
@ -83,11 +83,9 @@ main () {
|
||||||
|
|
||||||
_inside_openpype_tool="1"
|
_inside_openpype_tool="1"
|
||||||
|
|
||||||
# make sure Poetry is in PATH
|
|
||||||
if [[ -z $POETRY_HOME ]]; then
|
if [[ -z $POETRY_HOME ]]; then
|
||||||
export POETRY_HOME="$openpype_root/.poetry"
|
export POETRY_HOME="$openpype_root/.poetry"
|
||||||
fi
|
fi
|
||||||
export PATH="$POETRY_HOME/bin:$PATH"
|
|
||||||
|
|
||||||
echo -e "${BIGreen}>>>${RST} Reading Poetry ... \c"
|
echo -e "${BIGreen}>>>${RST} Reading Poetry ... \c"
|
||||||
if [ -f "$POETRY_HOME/bin/poetry" ]; then
|
if [ -f "$POETRY_HOME/bin/poetry" ]; then
|
||||||
|
|
@ -101,11 +99,11 @@ main () {
|
||||||
pushd "$openpype_root" > /dev/null || return > /dev/null
|
pushd "$openpype_root" > /dev/null || return > /dev/null
|
||||||
|
|
||||||
echo -e "${BIGreen}>>>${RST} Running apidoc ..."
|
echo -e "${BIGreen}>>>${RST} Running apidoc ..."
|
||||||
poetry run sphinx-apidoc -M -e -d 10 --ext-intersphinx --ext-todo --ext-coverage --ext-viewcode -o "$openpype_root/docs/source" igniter
|
"$POETRY_HOME/bin/poetry" run sphinx-apidoc -M -e -d 10 --ext-intersphinx --ext-todo --ext-coverage --ext-viewcode -o "$openpype_root/docs/source" igniter
|
||||||
poetry run sphinx-apidoc -M -e -d 10 --ext-intersphinx --ext-todo --ext-coverage --ext-viewcode -o "$openpype_root/docs/source" openpype vendor, openpype\vendor
|
"$POETRY_HOME/bin/poetry" run sphinx-apidoc -M -e -d 10 --ext-intersphinx --ext-todo --ext-coverage --ext-viewcode -o "$openpype_root/docs/source" openpype vendor, openpype\vendor
|
||||||
|
|
||||||
echo -e "${BIGreen}>>>${RST} Building html ..."
|
echo -e "${BIGreen}>>>${RST} Building html ..."
|
||||||
poetry run python3 "$openpype_root/setup.py" build_sphinx
|
"$POETRY_HOME/bin/poetry" run python3 "$openpype_root/setup.py" build_sphinx
|
||||||
}
|
}
|
||||||
|
|
||||||
main
|
main
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ Set-Location -Path $openpype_root
|
||||||
|
|
||||||
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
||||||
Write-Host "Reading Poetry ... " -NoNewline
|
Write-Host "Reading Poetry ... " -NoNewline
|
||||||
if (-not (Test-Path -PathType Container -Path "$openpype_root\.poetry\bin")) {
|
if (-not (Test-Path -PathType Container -Path "$($env:POETRY_HOME)\bin")) {
|
||||||
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
||||||
Write-Host "*** " -NoNewline -ForegroundColor Yellow
|
Write-Host "*** " -NoNewline -ForegroundColor Yellow
|
||||||
Write-Host "We need to install Poetry create virtual env first ..."
|
Write-Host "We need to install Poetry create virtual env first ..."
|
||||||
|
|
@ -56,5 +56,5 @@ if (-not (Test-Path -PathType Container -Path "$openpype_root\.poetry\bin")) {
|
||||||
Write-Host "OK" -ForegroundColor Green
|
Write-Host "OK" -ForegroundColor Green
|
||||||
}
|
}
|
||||||
|
|
||||||
& poetry run python "$($openpype_root)\start.py" projectmanager
|
& "$env:POETRY_HOME\bin\poetry" run python "$($openpype_root)\start.py" projectmanager
|
||||||
Set-Location -Path $current_dir
|
Set-Location -Path $current_dir
|
||||||
|
|
|
||||||
|
|
@ -79,11 +79,9 @@ main () {
|
||||||
|
|
||||||
_inside_openpype_tool="1"
|
_inside_openpype_tool="1"
|
||||||
|
|
||||||
# make sure Poetry is in PATH
|
|
||||||
if [[ -z $POETRY_HOME ]]; then
|
if [[ -z $POETRY_HOME ]]; then
|
||||||
export POETRY_HOME="$openpype_root/.poetry"
|
export POETRY_HOME="$openpype_root/.poetry"
|
||||||
fi
|
fi
|
||||||
export PATH="$POETRY_HOME/bin:$PATH"
|
|
||||||
|
|
||||||
pushd "$openpype_root" > /dev/null || return > /dev/null
|
pushd "$openpype_root" > /dev/null || return > /dev/null
|
||||||
|
|
||||||
|
|
@ -97,7 +95,7 @@ main () {
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -e "${BIGreen}>>>${RST} Generating zip from current sources ..."
|
echo -e "${BIGreen}>>>${RST} Generating zip from current sources ..."
|
||||||
poetry run python "$openpype_root/start.py" projectmanager
|
"$POETRY_HOME/bin/poetry" run python "$openpype_root/start.py" projectmanager
|
||||||
}
|
}
|
||||||
|
|
||||||
main
|
main
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ Set-Location -Path $openpype_root
|
||||||
|
|
||||||
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
||||||
Write-Host "Reading Poetry ... " -NoNewline
|
Write-Host "Reading Poetry ... " -NoNewline
|
||||||
if (-not (Test-Path -PathType Container -Path "$openpype_root\.poetry\bin")) {
|
if (-not (Test-Path -PathType Container -Path "$($env:POETRY_HOME)\bin")) {
|
||||||
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
||||||
Write-Host "*** " -NoNewline -ForegroundColor Yellow
|
Write-Host "*** " -NoNewline -ForegroundColor Yellow
|
||||||
Write-Host "We need to install Poetry create virtual env first ..."
|
Write-Host "We need to install Poetry create virtual env first ..."
|
||||||
|
|
@ -36,5 +36,5 @@ if (-not (Test-Path -PathType Container -Path "$openpype_root\.poetry\bin")) {
|
||||||
Write-Host "OK" -ForegroundColor Green
|
Write-Host "OK" -ForegroundColor Green
|
||||||
}
|
}
|
||||||
|
|
||||||
& poetry run python "$($openpype_root)\start.py" settings --dev
|
& "$env:POETRY_HOME\bin\poetry" run python "$($openpype_root)\start.py" settings --dev
|
||||||
Set-Location -Path $current_dir
|
Set-Location -Path $current_dir
|
||||||
|
|
@ -79,11 +79,9 @@ main () {
|
||||||
|
|
||||||
_inside_openpype_tool="1"
|
_inside_openpype_tool="1"
|
||||||
|
|
||||||
# make sure Poetry is in PATH
|
|
||||||
if [[ -z $POETRY_HOME ]]; then
|
if [[ -z $POETRY_HOME ]]; then
|
||||||
export POETRY_HOME="$openpype_root/.poetry"
|
export POETRY_HOME="$openpype_root/.poetry"
|
||||||
fi
|
fi
|
||||||
export PATH="$POETRY_HOME/bin:$PATH"
|
|
||||||
|
|
||||||
pushd "$openpype_root" > /dev/null || return > /dev/null
|
pushd "$openpype_root" > /dev/null || return > /dev/null
|
||||||
|
|
||||||
|
|
@ -97,7 +95,7 @@ main () {
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -e "${BIGreen}>>>${RST} Generating zip from current sources ..."
|
echo -e "${BIGreen}>>>${RST} Generating zip from current sources ..."
|
||||||
poetry run python3 "$openpype_root/start.py" settings --dev
|
"$POETRY_HOME/bin/poetry" run python3 "$openpype_root/start.py" settings --dev
|
||||||
}
|
}
|
||||||
|
|
||||||
main
|
main
|
||||||
|
|
|
||||||
|
|
@ -59,11 +59,9 @@ $openpype_root = (Get-Item $script_dir).parent.FullName
|
||||||
|
|
||||||
$env:_INSIDE_OPENPYPE_TOOL = "1"
|
$env:_INSIDE_OPENPYPE_TOOL = "1"
|
||||||
|
|
||||||
# make sure Poetry is in PATH
|
|
||||||
if (-not (Test-Path 'env:POETRY_HOME')) {
|
if (-not (Test-Path 'env:POETRY_HOME')) {
|
||||||
$env:POETRY_HOME = "$openpype_root\.poetry"
|
$env:POETRY_HOME = "$openpype_root\.poetry"
|
||||||
}
|
}
|
||||||
$env:PATH = "$($env:PATH);$($env:POETRY_HOME)\bin"
|
|
||||||
|
|
||||||
Set-Location -Path $openpype_root
|
Set-Location -Path $openpype_root
|
||||||
|
|
||||||
|
|
@ -83,7 +81,7 @@ Write-Host " ] ..." -ForegroundColor white
|
||||||
|
|
||||||
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
||||||
Write-Host "Reading Poetry ... " -NoNewline
|
Write-Host "Reading Poetry ... " -NoNewline
|
||||||
if (-not (Test-Path -PathType Container -Path "$openpype_root\.poetry\bin")) {
|
if (-not (Test-Path -PathType Container -Path "$($env:POETRY_HOME)\bin")) {
|
||||||
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
||||||
Write-Host "*** " -NoNewline -ForegroundColor Yellow
|
Write-Host "*** " -NoNewline -ForegroundColor Yellow
|
||||||
Write-Host "We need to install Poetry create virtual env first ..."
|
Write-Host "We need to install Poetry create virtual env first ..."
|
||||||
|
|
@ -102,7 +100,7 @@ Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||||
Write-Host "Testing OpenPype ..."
|
Write-Host "Testing OpenPype ..."
|
||||||
$original_pythonpath = $env:PYTHONPATH
|
$original_pythonpath = $env:PYTHONPATH
|
||||||
$env:PYTHONPATH="$($openpype_root);$($env:PYTHONPATH)"
|
$env:PYTHONPATH="$($openpype_root);$($env:PYTHONPATH)"
|
||||||
& poetry run pytest -x --capture=sys --print -W ignore::DeprecationWarning "$($openpype_root)/tests"
|
& "$env:POETRY_HOME\bin\poetry" run pytest -x --capture=sys --print -W ignore::DeprecationWarning "$($openpype_root)/tests"
|
||||||
$env:PYTHONPATH = $original_pythonpath
|
$env:PYTHONPATH = $original_pythonpath
|
||||||
|
|
||||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||||
|
|
|
||||||
|
|
@ -98,11 +98,9 @@ main () {
|
||||||
|
|
||||||
_inside_openpype_tool="1"
|
_inside_openpype_tool="1"
|
||||||
|
|
||||||
# make sure Poetry is in PATH
|
|
||||||
if [[ -z $POETRY_HOME ]]; then
|
if [[ -z $POETRY_HOME ]]; then
|
||||||
export POETRY_HOME="$openpype_root/.poetry"
|
export POETRY_HOME="$openpype_root/.poetry"
|
||||||
fi
|
fi
|
||||||
export PATH="$POETRY_HOME/bin:$PATH"
|
|
||||||
|
|
||||||
echo -e "${BIGreen}>>>${RST} Reading Poetry ... \c"
|
echo -e "${BIGreen}>>>${RST} Reading Poetry ... \c"
|
||||||
if [ -f "$POETRY_HOME/bin/poetry" ]; then
|
if [ -f "$POETRY_HOME/bin/poetry" ]; then
|
||||||
|
|
@ -118,7 +116,7 @@ main () {
|
||||||
echo -e "${BIGreen}>>>${RST} Testing OpenPype ..."
|
echo -e "${BIGreen}>>>${RST} Testing OpenPype ..."
|
||||||
original_pythonpath=$PYTHONPATH
|
original_pythonpath=$PYTHONPATH
|
||||||
export PYTHONPATH="$openpype_root:$PYTHONPATH"
|
export PYTHONPATH="$openpype_root:$PYTHONPATH"
|
||||||
poetry run pytest -x --capture=sys --print -W ignore::DeprecationWarning "$openpype_root/tests"
|
"$POETRY_HOME/bin/poetry" run pytest -x --capture=sys --print -W ignore::DeprecationWarning "$openpype_root/tests"
|
||||||
PYTHONPATH=$original_pythonpath
|
PYTHONPATH=$original_pythonpath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ Set-Location -Path $openpype_root
|
||||||
|
|
||||||
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
||||||
Write-Host "Reading Poetry ... " -NoNewline
|
Write-Host "Reading Poetry ... " -NoNewline
|
||||||
if (-not (Test-Path -PathType Container -Path "$openpype_root\.poetry\bin")) {
|
if (-not (Test-Path -PathType Container -Path "$($env:POETRY_HOME)\bin")) {
|
||||||
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
||||||
Write-Host "*** " -NoNewline -ForegroundColor Yellow
|
Write-Host "*** " -NoNewline -ForegroundColor Yellow
|
||||||
Write-Host "We need to install Poetry create virtual env first ..."
|
Write-Host "We need to install Poetry create virtual env first ..."
|
||||||
|
|
@ -35,5 +35,5 @@ if (-not (Test-Path -PathType Container -Path "$openpype_root\.poetry\bin")) {
|
||||||
Write-Host "OK" -ForegroundColor Green
|
Write-Host "OK" -ForegroundColor Green
|
||||||
}
|
}
|
||||||
|
|
||||||
& poetry run python "$($openpype_root)\start.py" tray --debug
|
& "$($env:POETRY_HOME)\bin\poetry" run python "$($openpype_root)\start.py" tray --debug
|
||||||
Set-Location -Path $current_dir
|
Set-Location -Path $current_dir
|
||||||
|
|
@ -56,11 +56,9 @@ main () {
|
||||||
|
|
||||||
_inside_openpype_tool="1"
|
_inside_openpype_tool="1"
|
||||||
|
|
||||||
# make sure Poetry is in PATH
|
|
||||||
if [[ -z $POETRY_HOME ]]; then
|
if [[ -z $POETRY_HOME ]]; then
|
||||||
export POETRY_HOME="$openpype_root/.poetry"
|
export POETRY_HOME="$openpype_root/.poetry"
|
||||||
fi
|
fi
|
||||||
export PATH="$POETRY_HOME/bin:$PATH"
|
|
||||||
|
|
||||||
echo -e "${BIGreen}>>>${RST} Reading Poetry ... \c"
|
echo -e "${BIGreen}>>>${RST} Reading Poetry ... \c"
|
||||||
if [ -f "$POETRY_HOME/bin/poetry" ]; then
|
if [ -f "$POETRY_HOME/bin/poetry" ]; then
|
||||||
|
|
@ -74,7 +72,7 @@ main () {
|
||||||
pushd "$openpype_root" > /dev/null || return > /dev/null
|
pushd "$openpype_root" > /dev/null || return > /dev/null
|
||||||
|
|
||||||
echo -e "${BIGreen}>>>${RST} Running OpenPype Tray with debug option ..."
|
echo -e "${BIGreen}>>>${RST} Running OpenPype Tray with debug option ..."
|
||||||
poetry run python3 "$openpype_root/start.py" tray --debug
|
"$POETRY_HOME/bin/poetry" run python3 "$openpype_root/start.py" tray --debug
|
||||||
}
|
}
|
||||||
|
|
||||||
main
|
main
|
||||||
Loading…
Add table
Add a link
Reference in a new issue