What is the best way, in python, to get the text of an AcDbText object?
I am working in python, win32com, and autoCAD. I would like to be able to do the following, via a python program:
Place objects into a selection set
Determine which are AcDbText objects
From those, extract the text and then delete.
I can do the first two things just fine. However, assuming textObj is the correct type of object, the following achieves half the remaining-- t will contain the text desired as a str:
t = textObj.copy().fieldcode()
Problem 1: As the code implies, this creates a copy of the object, right there in the drawing, and does not seem to provide a way to identify it later for deletion.
Problem 2: The original object resists deletion from the selection set. If selection is the selection set, then no variation of selection.clear(), selection.delete(), or selection.erase() does anything. (I have checked the length of selection set before and after the fieldcode() invocation-- the number of objects remains the same.)
I am puzzled that there does not seem to be a way to prize the text out of the object without copying it. What am I missing?
Per question in comments to an answer, the output of pprint(dir(textObj)) is:
['AddRef',
'Application',
'ArrayPolar',
'ArrayRectangular',
'Copy',
'Database',
'Delete',
'Document',
'EntityName',
'EntityTransparency',
'EntityType',
'Erase',
'GetBoundingBox',
'GetExtensionDictionary',
'GetIDsOfNames',
'GetTypeInfo',
'GetTypeInfoCount',
'GetXData',
'Handle',
'HasExtensionDictionary',
'Highlight',
'Hyperlinks',
'IntersectWith',
'Invoke',
'Layer',
'Linetype',
'LinetypeScale',
'Lineweight',
'Material',
'Mirror',
'Mirror3D',
'Move',
'ObjectID',
'ObjectName',
'OwnerID',
'PlotStyleName',
'QueryInterface',
'Release',
'Rotate',
'Rotate3D',
'ScaleEntity',
'SetXData',
'TransformBy',
'TrueColor',
'Update',
'Visible',
'_AddRef',
'_GetIDsOfNames',
'_GetTypeInfo',
'_IAcadEntity__com_ArrayPolar',
'_IAcadEntity__com_ArrayRectangular',
'_IAcadEntity__com_Copy',
'_IAcadEntity__com_GetBoundingBox',
'_IAcadEntity__com_Highlight',
'_IAcadEntity__com_IntersectWith',
'_IAcadEntity__com_Mirror',
'_IAcadEntity__com_Mirror3D',
'_IAcadEntity__com_Move',
'_IAcadEntity__com_Rotate',
'_IAcadEntity__com_Rotate3D',
'_IAcadEntity__com_ScaleEntity',
'_IAcadEntity__com_TransformBy',
'_IAcadEntity__com_Update',
'_IAcadEntity__com__get_EntityName',
'_IAcadEntity__com__get_EntityTransparency',
'_IAcadEntity__com__get_EntityType',
'_IAcadEntity__com__get_Hyperlinks',
'_IAcadEntity__com__get_Layer',
'_IAcadEntity__com__get_Linetype',
'_IAcadEntity__com__get_LinetypeScale',
'_IAcadEntity__com__get_Lineweight',
'_IAcadEntity__com__get_Material',
'_IAcadEntity__com__get_PlotStyleName',
'_IAcadEntity__com__get_TrueColor',
'_IAcadEntity__com__get_Visible',
'_IAcadEntity__com__get_color',
'_IAcadEntity__com__set_EntityTransparency',
'_IAcadEntity__com__set_Layer',
'_IAcadEntity__com__set_Linetype',
'_IAcadEntity__com__set_LinetypeScale',
'_IAcadEntity__com__set_Lineweight',
'_IAcadEntity__com__set_Material',
'_IAcadEntity__com__set_PlotStyleName',
'_IAcadEntity__com__set_TrueColor',
'_IAcadEntity__com__set_Visible',
'_IAcadEntity__com__set_color',
'_IAcadObject__com_Delete',
'_IAcadObject__com_Erase',
'_IAcadObject__com_GetExtensionDictionary',
'_IAcadObject__com_GetXData',
'_IAcadObject__com_SetXData',
'_IAcadObject__com__get_Application',
'_IAcadObject__com__get_Database',
'_IAcadObject__com__get_Document',
'_IAcadObject__com__get_Handle',
'_IAcadObject__com__get_HasExtensionDictionary',
'_IAcadObject__com__get_ObjectID',
'_IAcadObject__com__get_ObjectName',
'_IAcadObject__com__get_OwnerID',
'_IDispatch__com_GetIDsOfNames',
'_IDispatch__com_GetTypeInfo',
'_IDispatch__com_GetTypeInfoCount',
'_IDispatch__com_Invoke',
'_IUnknown__com_AddRef',
'_IUnknown__com_QueryInterface',
'_IUnknown__com_Release',
'_Invoke',
'_QueryInterface',
'_Release',
'__bool__',
'__class__',
'__cmp__',
'__com_interface__',
'__ctypes_from_outparam__',
'__del__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattr__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__map_case__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__setstate__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'_b_base_',
'_b_needsfree_',
'_case_insensitive_',
'_compointer_base__get_value',
'_idlflags_',
'_iid_',
'_invoke',
'_methods_',
'_needs_com_addref_',
'_objects',
'_type_',
'color',
'from_param',
'value']
Assuming textObj is either a single-line text object (AcDbText) or multiline text object (AcDbMText), then you should be able to obtain the text content using the TextString property, e.g.:
t = textObj.TextString
Note that the methods clear() & delete() when invoked on an ActiveX SelectionSet object do not delete the objects it contains, but rather remove the objects from the SelectionSet and delete the SelectionSet object respectively. Though, the erase() method should successfully erase all objects contained in the SelectionSet.
Though, to delete an object, you would typically just invoke the delete() method on the object itself, e.g.:
textObj.Delete()
Related
I have a 112 XML file, each contains a paragraph, like this: (this is one XML sample, we have 112 samples)
<?xml version='1.0' encoding='UTF-8'?>
<arggraph id="micro_b001" topic_id="waste_separation" stance="pro">
<edu id="e1"><![CDATA[Yes, it's annoying and cumbersome to separate your rubbish properly all the time.]]></edu>
<edu id="e2"><![CDATA[Three different bin bags stink away in the kitchen and have to be sorted into different wheelie bins.]]></edu>
<edu id="e3"><![CDATA[But still Germany produces way too much rubbish]]></edu>
<edu id="e4"><![CDATA[and too many resources are lost when what actually should be separated and recycled is burnt.]]></edu>
<edu id="e5"><![CDATA[We Berliners should take the chance and become pioneers in waste separation!]]></edu>
<adu id="a1" type="opp"/>
<adu id="a2" type="opp"/>
<adu id="a3" type="pro"/>
<adu id="a4" type="pro"/>
<adu id="a5" type="pro"/>
<edge id="c6" src="e1" trg="a1" type="seg"/>
<edge id="c7" src="e2" trg="a2" type="seg"/>
<edge id="c8" src="e3" trg="a3" type="seg"/>
<edge id="c9" src="e4" trg="a4" type="seg"/>
<edge id="c10" src="e5" trg="a5" type="seg"/>
<edge id="c1" src="a1" trg="a5" type="reb"/>
<edge id="c2" src="a2" trg="a1" type="sup"/>
<edge id="c3" src="a3" trg="c1" type="und"/>
<edge id="c4" src="a4" trg="c3" type="add"/>
</arggraph>
I want to read each of them in python and gather from each of the text that ends with "edu" ,and then saved them as
list of the list! like this
[[Yes, it's annoying and cumbersome to separate your rubbish properly all the time., Three different bin bags stink away in the kitchen and have to be sorted into different wheelie bins., But still Germany produces way too much rubbish
,and too many resources are lost when what actually should be separated and recycled is burnt , We Berliners should take the chance and become pioneers in waste separation!] , [
next XML content] ,[next, XML content],...
]]
I have tried this way
I have saved them all of them as list in myList
myList = []
myEdgesList=[]
#read the whole text from
for root, dirs, files in os.walk(path):
for file in files:
if file.endswith('.xml'):
with open(os.path.join(root, file), encoding="UTF-8") as content:
tree = ET.parse(content)
myList.append(tree)
then:
ParaList=[]
EduList=[]
for k in myList:
a=k.findall('.//edu')
for l in a:
EduList.append(l.text)
ParaList.append(EduList)
but the result only gives me a flat list of all sentences (576) and not a list of 112 paragraphs
can someone help me?
Assuming that myList is a list of parsed XML documents, moving ParaList.append(EduList) inside the main for loop should fix it for you. You also need to reset the EduList once per document, so also move EduList=[] inside the main loop:
ParaList=[]
for k in myList:
EduList=[]
a=k.findall('.//edu')
for l in a:
EduList.append(l.text)
ParaList.append(EduList)
Now the extracted content of each XML document is appended to ParaList once per document.
A better way to write this code is to use a list comprehension to process the matching lines:
ParaList=[]
for k in myList:
ParaList.append([l.text for l in k.findall('.//edu')])
Or you could even do it in one line using a nested list comprehension:
ParaList = [[l.text for l in k.findall('.//edu')] for k in myList]
From the documentation:
Without arguments, return the list of names in the current local scope. With an argument, attempt to return a list of valid attributes for that object.
So i try see inside the scrapy module
import scrapy is a module right, or im wrong?
>>>dir(scrapy)
NameError: name 'scrapy' is not defined
Im complete newb in python and just try understand how works.
How can i see inside modules like documentation examples
>>> dir(sys)
['__displayhook__', '__doc__', '__excepthook__', '__loader__', '__name__',
'__package__', '__stderr__', '__stdin__', '__stdout__',
'_clear_type_cache', '_current_frames', '_debugmallocstats', '_getframe',
'_home', '_mercurial', '_xoptions', 'abiflags', 'api_version', 'argv',
'base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder',
'call_tracing', 'callstats', 'copyright', 'displayhook',
'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix',
'executable', 'exit', 'flags', 'float_info', 'float_repr_style',
'getcheckinterval', 'getdefaultencoding', 'getdlopenflags',
'getfilesystemencoding', 'getobjects', 'getprofile', 'getrecursionlimit',
'getrefcount', 'getsizeof', 'getswitchinterval', 'gettotalrefcount',
'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info',
'intern', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path',
'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1',
'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit',
'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout',
'thread_info', 'version', 'version_info', 'warnoptions']
Try this from your python interpreter:
In [1]: import scrapy
In [2]: dir(scrapy)
Out[2]:
['Field',
'FormRequest',
'Item',
'Request',
'Selector',
'Spider',
'__all__',
'__builtins__',
'__cached__',
'__doc__',
'__file__',
'__loader__',
'__name__',
'__package__',
'__path__',
'__spec__',
'__version__',
'_txv',
'exceptions',
'http',
'item',
'link',
'selector',
'signals',
'spiders',
'twisted_version',
'utils',
'version_info']
This worked for me in both Python 2 and 3. I have also confirmed that it works in both iPython and the standard interpreter. If it does not work for you even with the import, your environment may have gotten messed up in some way, and we can troubleshoot further.
import scrapy is a module right, or im wrong?
In this case scrapy is a module, and import scrapy is the syntax for making that module available in whatever context you are invoking the import from. This section of the Python tutorial has information on modules and importing them.
Example code fragment from a base class:
def build_extra_content(self):
grp = 'choice_dialog'
extra_content = GridLayout(cols=2)
lb_width = self.width - 2 * self.choice_height
for choice in self.choices:
cb = CheckBox(group=grp,
size_hint=(None, None), size=(self.choice_height, self.choice_height))
lb = Label(markup=True, text=choice, halign='left', valign='middle',
size_hint=(None, None), size=(lb_width, self.choice_height))
lb.texture_size = (lb_width, self.choice_height)
extra_content.add_widget(cb)
extra_content.add_widget(lb)
# TODO: check the checkbox when the label is touched.
def _lb_press(*args):
print(args)
cb.bind(on_touch_down=_lb_press)
return extra_content
The content is displayed in this dialog:
I have two questions. First: why the text is aligned to the center? I have already set absolute sizes for both the label and its texture size, and set halign='left'. But the text is still aligned to the center. Why?
Second: I wanted the labels to be clickable/touchable. E.g. the checkboxes should be selected by touching their corresponding labels. Whenever I click on a single label or checkbox, this is printed:
(<kivy.uix.checkbox.CheckBox object at 0x0B2C01B8>, <MouseMotionEvent button="left" device="mouse" double_tap_time="0" dpos="(0.0, 0.0)" dsx="0.0" dsy="0.0" dsz="0.0" dx="0.0" dy="0.0" dz="0.0" grab_current="None" grab_exclusive_class="None" grab_list="[]" grab_state="False" id="mouse3" is_double_tap="False" is_mouse_scrolling="False" is_touch="True" is_triple_tap="False" opos="(644.0, 379.0)" osx="0.503125" osy="0.47375" osz="0.0" ox="644.0" oy="379.0" oz="0.0" pos="(644.0, 379.0)" ppos="(644.0, 379.0)" profile="['pos', 'button']" psx="0.503125" psy="0.47375" psz="0.0" push_attrs="('x', 'y', 'z', 'dx', 'dy', 'dz', 'ox', 'oy', 'oz', 'px', 'py', 'pz', 'pos')" push_attrs_stack="[]" px="644.0" py="379.0" pz="0.0" shape="None" spos="(0.503125, 0.47375)" sx="0.503125" sy="0.47375" sz="0.0" time_end="-1" time_start="1507722998.229789" time_update="1507722998.229789" triple_tap_time="0" ud="{}" uid="3" x="644.0" y="379.0" z="0.0">)
(<kivy.uix.checkbox.CheckBox object at 0x0B5FC2D0>, <MouseMotionEvent button="left" device="mouse" double_tap_time="0" dpos="(0.0, 0.0)" dsx="0.0" dsy="0.0" dsz="0.0" dx="0.0" dy="0.0" dz="0.0" grab_current="None" grab_exclusive_class="None" grab_list="[]" grab_state="False" id="mouse3" is_double_tap="False" is_mouse_scrolling="False" is_touch="True" is_triple_tap="False" opos="(644.0, 379.0)" osx="0.503125" osy="0.47375" osz="0.0" ox="644.0" oy="379.0" oz="0.0" pos="(644.0, 379.0)" ppos="(644.0, 379.0)" profile="['pos', 'button']" psx="0.503125" psy="0.47375" psz="0.0" push_attrs="('x', 'y', 'z', 'dx', 'dy', 'dz', 'ox', 'oy', 'oz', 'px', 'py', 'pz', 'pos')" push_attrs_stack="[]" px="644.0" py="379.0" pz="0.0" shape="None" spos="(0.503125, 0.47375)" sx="0.503125" sy="0.47375" sz="0.0" time_end="-1" time_start="1507722998.229789" time_update="1507722998.229789" triple_tap_time="0" ud="{}" uid="3" x="644.0" y="379.0" z="0.0">)
(<kivy.uix.checkbox.CheckBox object at 0x0B5F3768>, <MouseMotionEvent button="left" device="mouse" double_tap_time="0" dpos="(0.0, 0.0)" dsx="0.0" dsy="0.0" dsz="0.0" dx="0.0" dy="0.0" dz="0.0" grab_current="None" grab_exclusive_class="None" grab_list="[]" grab_state="False" id="mouse3" is_double_tap="False" is_mouse_scrolling="False" is_touch="True" is_triple_tap="False" opos="(644.0, 379.0)" osx="0.503125" osy="0.47375" osz="0.0" ox="644.0" oy="379.0" oz="0.0" pos="(644.0, 379.0)" ppos="(644.0, 379.0)" profile="['pos', 'button']" psx="0.503125" psy="0.47375" psz="0.0" push_attrs="('x', 'y', 'z', 'dx', 'dy', 'dz', 'ox', 'oy', 'oz', 'px', 'py', 'pz', 'pos')" push_attrs_stack="[]" px="644.0" py="379.0" pz="0.0" shape="None" spos="(0.503125, 0.47375)" sx="0.503125" sy="0.47375" sz="0.0" time_end="-1" time_start="1507722998.229789" time_update="1507722998.229789" triple_tap_time="0" ud="{}" uid="3" x="644.0" y="379.0" z="0.0">)
Actually it doesn't matter where I click. Even if I click outside the GridLayout, always all labels will trigger the touch event. But why? I only want the one under my finger.
Thanks
First: why the text is aligned to the center? I
have already set absolute sizes for both the label and its texture
size, and set halign='left'. But the text is still aligned to the
center. Why?
You're setting texture_size, but you should set text_size instead.
Second: I wanted the labels to be clickable/touchable. E.g. the
checkboxes should be selected by touching their corresponding labels.
Whenever I click on a single label or checkbox, this is printed:
In Kivy every widget receive touch event. You should check if touch happened inside your label manually:
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
# The touch has occurred inside the widgets area. Do stuff!
pass
Here is the answer to your second question.
Note
By default, touch events are dispatched to all currently displayed
widgets. This means widgets receive the touch event whether it occurs
within their physical area or not.
In order to provide the maximum flexibility, Kivy dispatches the
events to all the widgets and lets them decide how to react to them.
If you only want to respond to touch events inside the widget, you
simply check:
Example
class ProjectSelectButton(Button):
def click_on_button(self, instance, touch, *args):
print(instance)
if self.collide_point(*touch.pos):
if touch.button == 'right':
print(self.id, "right mouse clicked")
elif touch.buttom == 'left':
print(self.id, "left mouse clicked")
return True
return super(ProjectSelectButton, self).on_touch_down(touch)
I'm using the jira-python module and was not able to figure out how
to retrieve the creation date of a Jira issue link (inwardIssue, outwardIssue)
I looked at https://jira.readthedocs.io/en/master/api.html but could not seem
to find what i'm looking for.
For a given issuelink, the Python "dir()" function shows me:
['JIRA_BASE_URL', '_READABLE_IDS', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattr__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_base_url', '_default_headers', '_get_url', '_load', '_options', '_parse_raw', '_resource', '_session', 'delete', 'find', 'id', 'inwardIssue', 'outwardIssue', 'raw', 'self', 'type', 'update']
Any pointers would be greatly appreciated.
Thanks
--Andrew
For a given issue, the creation date is:
issue.fields.created
IssueLink types do not included information about when they were "created" (in this case the moment of linkage and not the creation of said linked issue). This information can be abstracted from an issue's changelog (eg: PROJECT-10):
issue = jira.issue('PROJECT-10', expand='changelog')
for history in issue.changelog.histories:
for item in history.items:
if item.field == 'Link':
print("{} was linked to {} at {}".format(item.toString.split()[-1], issue, history.created))
I was wondering if anyone knew how to add numbers (purely for reference) to Kivy's FileChooserListView such that the file list is displayed like:
# Name Size
1. File 1 2k
2. File 2 2k
3. File 3 2k
...
OK, it's not a perfect answer but here's what I tried to do:
First thing was to edit kivy's default filechooser.py file. Find this section:
ctx = {'name': basename(fn),
'get_nice_size': get_nice_size,
'path': fn,
'controller': wself,
'isdir': self.file_system.is_dir(fn),
'parent': parent,
'sep': sep}
and change it to:
ctx = {'name': basename(fn),
'get_nice_size': get_nice_size,
'path': fn,
'controller': wself,
'isdir': self.file_system.is_dir(fn),
'parent': parent,
'sep': sep,
'index': index}
Next up, find kivy's style.kv file (you could probably create a custom class to do this but I was being lazy!). Look for this section [FileListEntry#FloatLayout+TreeViewNode]:
I then took this part:
Label:
id: filename
text_size: self.width, None
halign: 'left'
shorten: True
text: ctx.name
and changed it to:
Label:
id: filename
text_size: self.width, None
halign: 'left'
shorten: True
text: "{}. {}".format(ctx.index, ctx.name)
As per my comment above, it seems to throw an error if you try to navigate folders.
It may be the case that one of the kivy experts knows a better way of doing this.
I know this is quite late but to complete the answer of elParaguayo, you also have to replace the lines
pardir = self._create_entry_widget(dict(
name=back, size='', path=new_path, controller=ref(self),
isdir=True, parent=None, sep=sep,
get_nice_size=lambda: ''))
with
pardir = self._create_entry_widget(dict(
name=back, size='', path=new_path, controller=ref(self),
isdir=True, parent=None, sep=sep,
get_nice_size=lambda: '', index= 0))
(be careful there are 2 occurences of these lines). This is what throws the exception when you navigate: the parent directory ../ is not created with the same lines as the other files.
Also, I would advise to create a local copy of filechooser.py and style.kv and load them into your app instead of modifying the source code of the kivy modules.