Hello,
I am copying several elements from links or documents to the current project file opened with Dynamo with the nodes of rhythm or springs, but it takes so long because majority of elements contain other elements that Revit indicates they are duplicated and if I want to overwrite with OK button.
is possible to copy all without any question of Duplicate Types?
You would have to use a CopyElements method with CopyPasteOptions so that you can set the SetDuplicateTypeNamesHandler to ignore duplicates.
2 Likes
You’d have to write the code using those methods and members I linked.
2 Likes
Hello @Nick_Boyts
I understand that I would have to define the CopyPasteOptions of the code.
But how is the variable of CopyPasteOptions defined? I tried adding also this code but it seems it needs more definition:
copy = ElementTransformUtils.CopyElements(Document, ICollection(ElementId), Document, Transform, CopyPasteOptions )
options = CopyPasteOptions()
options.SetDuplicateTypeNamesHandler()
copy = ElementTransformUtils.CopyElements(Document, ICollection(ElementId), Document, Transform, options)
I suggest doing some research on python coding with the Revit API. It can seem like a big step but it’s incredibly powerful once you get comfortable with it.
The argument you have to supply is the object in green, IDuplicateTypeNamesHandler
. If you click on it it will explain what it does and give you a link to all its members
. You’d have to check the members
to see how that value is set. You may even have to do this multiple times if the argument is another method that needs defining.
Hello
the implementation of a Net Interface is quite specific in Python
here is a sample example
import clr
import sys
import System
from System.Collections.Generic import List
# all imports and some code
# ...
# ...
# ...
# current_doc = ...
# ...
class CustomCopyHandler(IDuplicateTypeNamesHandler):
def OnDuplicateTypeNamesFound(self, args):
return DuplicateTypeAction.UseDestinationTypes
souceDoc = UnwrapElement(IN[0])
myElements = UnwrapElement(IN[1])
copyOptions = CopyPasteOptions()
copyOptions.SetDuplicateTypeNamesHandler(CustomCopyHandler())
# start transaction
TransactionManager.Instance.ForceCloseTransaction()
TransactionManager.Instance.EnsureInTransaction(current_doc)
myElementIds = List[ElementId]([x.Id for x in myElements])
newCopyElementIds = ElementTransformUtils.CopyElements(souceDoc, myElementIds, current_doc, None , copyOptions)
# rest of code
# ...
# ...
TransactionManager.Instance.TransactionTaskDone()
6 Likes
SeanP
December 14, 2021, 2:43pm
#9
@c.poupin would you know what Argument the CopyHandler is expecting? I have not actually had to pass things like this in the past. @solamour @Michael_Kirschner2
import clr
import sys
import System
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
clr.AddReference('System')
from System.Collections.Generic import List
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.Elements)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
class CustomCopyHandler(IDuplicateTypeNamesHandler):
def OnDuplicateTypeNamesFound(self, args):
return DuplicateTypeAction.UseDestinationTypes
doc = DocumentManager.Instance.CurrentDBDocument
#Preparing input from dynamo to revit
linkInst = UnwrapElement(IN[0])
linkViews = UnwrapElement(IN[1])
newViews = UnwrapElement(IN[2])
LinkIds = []
NewIds = []
Items = []
#Do some action in a Transaction
TransactionManager.Instance.EnsureInTransaction(doc)
opts = CopyPasteOptions()
opts.SetDuplicateTypeNamesHandler(CustomCopyHandler()) #Line 47 from Error
Items.append(ElementTransformUtils.CopyElements(linkView,List[ElementId](oldItems),newView,Transform.Identity,opts))
UPDATE:
It works fine if I run it against IP2, is there something in CP3 that I need to adjust for the interface?
1 Like
Hi @SeanP
it’s a know issue
you can try to change the namespace of the class (with __namespace__
attribute) but it’s unstable currently
opened 07:46AM - 04 Aug 17 UTC
enhancement
### Environment
- Pythonnet version: 2.3.0
- Python version: 3.5.3 32-bi… t/64/bit
- Operating System: Windows 7 Pro SP1 32-bit/64-bit
### Details
- Describe what you were trying to get done.
I want to develop python class using .NET base class in Spyder 3. I can only once use "Run" in Spyder. On next attemp TypeError comes.
Python interpreter is started once by Spyder and runs continuously. Each time user pushes "Run" button the script is executed. This employs python basic concept that you can redefine any python native class any time. But pythonnet breaks this. I believe it is a bug, because if I comment "__namespace__" attribute in my class definitions than it works.
- What commands did you run to trigger this issue? If you can provide a
[Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve)
this will help us understand the issue.
[test3.zip](https://github.com/pythonnet/pythonnet/files/1199582/test3.zip)
1. start cc.bat in Visual Studio 2015 prompt to compile class.dll (or use attached one)
2. start Spyder 3
3. open test3.py in Spyder
4. push "run"
5. push "run" again
Console outputs in Spyder after 2nd execution looks like:
```
Python 3.5.3 |Continuum Analytics, Inc.| (default, Feb 22 2017, 21:49:24) [MSC v.1900 32 bit (Intel)]
Type "copyright", "credits" or "license" for more information.
IPython 5.3.0 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
runfile('D:/temp/1/test3.py', wdir='D:/temp/1')
Hello
runfile('D:/temp/1/test3.py', wdir='D:/temp/1')
Reloaded modules: Axa.Core.Prototype, Axa.Core, Axa, CLR, clr
Traceback (most recent call last):
File "<ipython-input-2-a72cc270f94b>", line 1, in <module>
runfile('D:/temp/1/test3.py', wdir='D:/temp/1')
File "C:\Miniconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 866, in runfile
execfile(filename, namespace)
File "C:\Miniconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 102, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)
File "D:/temp/1/test3.py", line 8, in <module>
class MyClass(Prototype.IProcessControl):
TypeError: Duplicate type name within an assembly.
```
pyRevit has similar issue
opened 08:47PM - 14 Sep 19 UTC
Heisenbug
cpython
**Describe the bug**
CPython engine is unstable when an object that is created … in cpython scope is passed to Revit API. Seems like Revit gets stuck when trying to garbage collect the passed object(?!)
The script below, will halt Revit after a couple of executions. The script does not cause any halts when `rebars = select_objects()` is used. (Uncomment the `rebars = select_objects()` line and comment out the `rebars = select_objects_by_category('Walls')` to change the test)
The issue seems to be related to passing an instance of `CategoriesFilter` to Revit API. Note that this might be related to #686
```python
from pyrevit import EXEC_PARAMS
from pyrevit import revit, UI
class CategoriesFilter(UI.Selection.ISelectionFilter):
__namespace__ = EXEC_PARAMS.exec_id
def __init__(self, names):
self.names = names
def AllowElement(self, element):
return element.Category.Name in self.names
def AllowReference(self, refer, point):
return False
def select_objects_by_category(*names):
references = \
revit.uidoc.Selection.PickObjects(
UI.Selection.ObjectType.Element,
CategoriesFilter(names),
'Pick {}'.format(', '.join(names))
)
return [revit.doc.GetElement(reference) for reference in references]
def select_objects():
references = \
revit.uidoc.Selection.PickObjects(UI.Selection.ObjectType.Element)
return [revit.doc.GetElement(reference) for reference in references]
def main():
# rebars = select_objects()
rebars = select_objects_by_category('Walls')
print(rebars)
main()
```
for information the next version of PythonNet has many BREAKING
# Changelog
All notable changes to Python.NET will be documented in this file. This
project adheres to [Semantic Versioning][].
This document follows the conventions laid out in [Keep a CHANGELOG][].
## [Unreleased][]
### Added
- Ability to instantiate new .NET arrays using `Array[T](dim1, dim2, ...)` syntax
- Python operator method will call C# operator method for supported binary and unary operators ([#1324][p1324]).
- Add GetPythonThreadID and Interrupt methods in PythonEngine
- Ability to implement delegates with `ref` and `out` parameters in Python, by returning the modified parameter values in a tuple. ([#1355][i1355])
- `PyType` - a wrapper for Python type objects, that also permits creating new heap types from `TypeSpec`
- Improved exception handling:
* exceptions can now be converted with codecs
* `InnerException` and `__cause__` are propagated properly
- `__name__` and `__signature__` to reflected .NET methods
This file has been truncated. show original
Till date (PythonNet and/or IronPython can evolve), I use both 2 engines, each one has it’s own advantages:
IronPython has better .Net integration
CPython3 / PythonNet allows to use an updated version of Python (with modern packages) and with a .Net integration but not as advanced as IronPython
but all this remains my own opinion
2 Likes
SeanP
December 14, 2021, 3:53pm
#11
Thank you as always @c.poupin the namespace attribute worked for me in this instance.
class CustomCopyHandler(IDuplicateTypeNamesHandler):
__namespace__ = "Autodesk.Revit.DB"
def OnDuplicateTypeNamesFound(self, args):
return DuplicateTypeAction.UseDestinationTypes
1 Like
this method works once per Revit session
An example with IFamilyLoadOptions interface
2 Likes
SeanP
December 14, 2021, 4:59pm
#13
Yes, found this out rather quickly, and went back to IP2. I’ll stay there until there is another way to do it, but this is also why I’ll be eventually rolling this into an addin and remove the issue completely.
Thanks again!
2 Likes