Release Notes
3.0.0 (2023-08-13)
Highlights
Removed all camel case or non-standard single dash long command line interface (cli) parameters. Example: command line arguments like -parent will become –parent. Commands that support camel case like –parentId will be changed to –parent-id.
Remove support for Python 3.7 due to its end of life and support Python 3.11
Support Synapse JSON schema services
Bug Fixes
[SYNPY-570] - warning messages when downloading if files in the cache already
[SYNPY-622] - Constructor for SubmissionStatus is not correctly implemented
[SYNPY-1242] - _loggedIn() function doesn’t work
[SYNPY-1269] - Integration test failures against release-456
[SYNPY-1271] - Integration test failure against release-458
Stories
[SYNPY-737] - deprecate single dash, multi-letter named params in command line client
[SYNPY-1012] - Synapse Command Line documentation is not distinct from Synapse Python Client documentations
[SYNPY-1213] - Add “public” and “registered users” group to setPermissions doc
[SYNPY-1245] - Fix old links to synapse docs
[SYNPY-1246] - Support Python 3.11
[SYNPY-1122] - JSON Schema support
[SYNPY-1255] - Support pandas 2.0 in python client
[SYNPY-1266] - Support uploads to GCP external bucket
[SYNPY-1270] - Deprecate the use of date_parser and parse_date in pd.read_csv in table module
[SYNPY-716] - Deprecate and remove asInteger()
[SYNPY-1227] - Run black the Python auto formatter on the files
2.7.2 (2023-06-02)
Highlights
[SYNPY-1267] - Lock down urllib3
[SYNPY-1268] - Add deprecation warning for non-support login arguments
Next major release (3.0.0)…
Support only pandas >= 1.5
Remove support for Python 3.7 due to its end of life.
There will be major cosmetic changes to the cli such as removing all camel case or non-standard single dash long command line interface (cli) parameters. Example: command line arguments like -parent will become –parent. Commands that support camel case like –parentId will be changed to –parent-id.
2.7.1 (2023-04-11)
Highlights
Locked down pandas version to only support pandas < 1.5
Next major release (3.0.0)…
Support only pandas >= 1.5
Remove support for Python 3.7 due to its end of life.
There will be major cosmetic changes to the cli such as removing all camel case or non-standard single dash long command line interface (cli) parameters. Example: command line arguments like -parent will become –parent. Commands that support camel case like –parentId will be changed to –parent-id.
2.7.0 (2022-09-16)
Highlights
Added support for Datasets
# from python import synapseclient import synapseutils syn = synapseclient.login() dataset_items = [ {'entityId': "syn000", 'versionNumber': 1}, {...}, ] dataset = synapseclient.Dataset( name="My Dataset", parent=project, dataset_items=dataset_items ) dataset = syn.store(dataset) # Add/remove specific Synapse IDs to/from the Dataset dataset.add_item({'entityId': "syn111", 'versionNumber': 1}) dataset.remove_item("syn000") dataset = syn.store(dataset) # Add a single Folder to the Dataset # this will recursively add all the files in the folder dataset.add_folder("syn123") # Add a list of Folders, overwriting any existing files in the dataset dataset.add_folders(["syn456", "syn789"], force=True) dataset = syn.store(dataset) # Create snapshot version of dataset syn.create_snapshot_version( dataset.id, label="v1.0", comment="This is version 1" )
Added support for downloading from download cart. You can use this feature by first adding items to your download cart on Synapse.
# from python import synapseclient import synapseutils syn = synapseclient.login() manifest_path = syn.get_download_list()
# from command line synapse get-download-list
Next major release (3.0.0) there will be major cosmetic changes to the cli such as removing all camel case or non-standard single dash long command line interface (cli) parameters. Example: command line arguments like -parent will become –parent. Commands that support camel case like –parentId will be changed to –parent-id.
Bug Fixes
[SYNPY-226] - isConsistent fails as parameter for table query
[SYNPY-562] - Make sure SQL functions, including “year”, are quoted correctly
[SYNPY-1031] - File version increments with 400 client error
[SYNPY-1219] - Update Entity class to be compatible with the new Dataset entity
[SYNPY-1224] - Correct SynapseUnmetAccessRestrictions message
[SYNPY-1237] - as_table_columns function is mishandling mixed data types
Stories
[SYNPY-63] - py: use metaclass to replace the _entity_type_to_class hack
[SYNPY-992] - synapseutils changeFileMetadata missing syn parameter docstring
[SYNPY-1175] - Programmatic Support for Download V2 via Py Client
[SYNPY-1193] - Support Datasets functionality
[SYNPY-1221] - Set up gh-action: black, the python auto formatter on the python client
Tasks
[SYNPY-566] - Clarify expected list format for sync manifest
[SYNPY-1053] - Increase documentation of forceVersion in syncToSynapse
[SYNPY-1145] - Link to manifest format in CLI sync command usage help
[SYNPY-1226] - Leverage ViewBase for Datasets instead of SchemaBase
[SYNPY-1235] - Create codeql scanning workflow
[SYNPY-1207] - Support syn.get() on a dataset
2.6.0 (2022-04-19)
Highlights
Next major release (3.0.0) there will be major cosmetic changes to the cli such as removing all camel case or non-standard single dash long command line interface (cli) parameters. Example: command line arguments like -parent will become –parent. Commands that support camel case like –parentId will be changed to –parent-id.
Added support for materialized views
# from python import synapseclient import synapseutils syn = synapseclient.login() view = synapseclient.MaterializedViewSchema( name="test-material-view", parent="syn34234", definingSQL="SELECT * FROM syn111 F JOIN syn2222 P on (F.PATIENT_ID = P.PATIENT_ID)" ) view_ent = syn.store(view)
Removed support for Python 3.6 and added support for Python 3.10
Add function to create Synapse config file
# from the command line synapse config
Bug Fixes
[SYNPY-1204] - Python 3.10 compatibility
Stories
[SYNPY-728] - Improve error message when pandas is not available
[SYNPY-974] - Documentation for generateManifest
[SYNPY-1209] - Support for MaterializedViews in Py Client
Tasks
[SYNPY-1174] - Add function to create Synapse config file
[SYNPY-1176] - syncToSynapse aborted + silent failure of file upload
[SYNPY-1184] - Add includeTypes to synapseutils.walk()
[SYNPY-1189] - Document “maximumListLength” parameter for Column
[SYNPY-1196] - Expose forceVersion on changeFileMetadata
[SYNPY-1205] - Python 3.6 EOL - Remove support for 3.6
[SYNPY-1212] - Include dataset as an entity type to return in getChildren()
2.5.1 (2021-12-02)
Highlights
Next major release (3.0.0) there will be major cosmetic changes to the cli such as removing all camel case or non-standard single dash long command line interface (cli) parameters. Example: command line arguments like -parent will become –parent. Commands that support camel case like –parentId will be changed to –parent-id.
Bug Fixes
[SYNPY-1197] - Schema is a string and strings don’t have columns_to_store attributes
Stories
2.5.0 (2021-10-05)
Highlights
Added ability to generate a manifest file from your local directory structure.
# from the command line # write the manifest to manifest.tsv synapse manifest --parent-id syn123 --manifest-file ./manifest.tsv /path/to/local/directory # stdout synapse manifest --parent-id syn123 /path/to/local/directory
Added ability to pipe manifest stdout into sync function.
# from the command line synapse manifest --parent-id syn123 ./docs/ | synapse sync -
Added ability to return summary statistics of csv and tsv files stored in Synapse.
# from python import synapseclient import synapseutils syn = synapseclient.login() statistics = synapseutils.describe(syn=syn, entity="syn12345") print(statistics) { "column1": { "dtype": "object", "mode": "FOOBAR" }, "column2": { "dtype": "int64", "mode": 1, "min": 1, "max": 2, "mean": 1.4 }, "column3": { "dtype": "bool", "mode": false, "min": false, "max": true, "mean": 0.5 } }
Next major release (3.0.0) there will be major cosmetic changes to the cli such as removing all camel case or non-standard single dash long command line interface (cli) parameters. Example: command line arguments like -parent will become –parent. Commands that support camel case like –parentId will be changed to –parent-id.
Bug Fixes
[SYNPY-669] - Signing of Synapse authentication header does not correctly URL encode the URL path
[SYNPY-770] - Files failing to upload using syncToSynapse
[SYNPY-1123] - All tables erroring when indexing
[SYNPY-1146] - Error writing Booleans from Python dataframes into Boolean columns in a Synapse table
[SYNPY-1156] - datetimes in a Pandas dataframe are not properly stored to Synapse
Stories
[SYNPY-726] - mirror local folder structure for bulk upload
[SYNPY-1163] - Expose synId with syn get -r
[SYNPY-1165] - Generate manifest template from local folder structure
[SYNPY-1167] - Support for Quick Summary Statistics on CSV and TSV files
Tasks
[SYNPY-1169] - Integration tests failures in develop branch against stack-371
[SYNPY-1172] - Passing a pandas dataframe with a column called “read” breaks the type parsing in as_table_columns()
[SYNPY-1173] - Support DATE_LIST, ENTITYID_LIST, USERID_LIST table columns
[SYNPY-1188] - Support piping of synapse manifest stdout in synapse sync function
2.4.0 (2021-07-08)
Highlights
Added ability to authenticate from a
SYNAPSE_AUTH_TOKEN
environment variable set with a valid personal access token.# e.g. set environment variable prior to invoking a Synapse command or running a program that uses synapseclient SYNAPSE_AUTH_TOKEN='<my_personal_access_token>' synapse <subcommand options>
The environment variable will take priority over credentials in the user’s
.synapseConfig
file or any credentials saved in a prior login using the remember me option.See here for more details on usage.
Added ability to silence all console output.
# from the command line, use the --silent option with any synapse subcommand, here it will suppress the download progress indicator synapse --silent get <synid>
# from code using synapseclient, pass the silent option to the Synapse constructor import synapseclient syn = synapseclient.Synapse(silent=True) syn.login() syn.get(<synid>)
Improved robustness during downloads with unstable connections. Specifically the client will automatically recover when encoutering some types of network errors that previously would have caused a download to start over as indicated by a reset progress bar.
Bug Fixes
[SYNPY-198] - get: Unmet access requirement should not raise error if entity not downloadable
[SYNPY-959] - FileEntity ‘path’ property has wrong separator in Windows
[SYNPY-1113] - Confusing error when putting the positional FILE at the end of the synapse store command with an optional n-arg
[SYNPY-1128] - failures downloading 14G vcf file
[SYNPY-1130] - Migration tool trying to move URL-linked data
[SYNPY-1134] - 500 error during part copy to AWS presigned url
[SYNPY-1135] - Exceeding part limit during AD Migration
[SYNPY-1136] - Connection aborted to AWS part copy to presigned url during AD Migration
[SYNPY-1141] - synapse get command line nargs usage/error
[SYNPY-1150] - Boolean-like string columns being reformatted (TRUE/FALSE to True/False)
[SYNPY-1158] - race condition in test_caching.py#test_threaded_access
[SYNPY-1159] - logging in with an email address and an authToken gives spurious error
[SYNPY-1161] - ChunkEncodingError encountered from external collaborator during a synapseclient download
Improvements
[SYNPY-638] - add after date to cache purge
[SYNPY-929] - silent parameter for all functions which default to writing to stdout
[SYNPY-1068] - Should show some progress indicator during upload md5 calculation
[SYNPY-1125] - Allow login with environment variables
[SYNPY-1138] - When using boto3 client to upload a file, also include ACL to give bucket owner full access
Tasks
[SYNPY-948] - command line client set-annotations does not return proper error code when there’s a problem
[SYNPY-1024] - remove reference to deprecated ‘status’ field from Evaluation
[SYNPY-1143] - indicate in CLI doc’s that select statement requires double quotes
2.3.1 (2021-04-13)
Highlights
Entities can be annotated with boolean datatypes, for example:
file = synapseclient.File('/path/to/file', parentId='syn123', synapse_is_great=True) syn.store(file)
synapseclient is additionally packaged as a Python wheel.
Bug Fixes
[SYNPY-829] - syn.store always updates annotations
[SYNPY-1033] - If versionComment is left blank, previous version comment populates
Improvements
[SYNPY-1120] - Build wheel distributions
[SYNPY-1129] - Support boolean annotations in Python client
2.3.0 (2021-03-03)
Highlights
The index_files_for_migration and migrate_indexed_files functions are added to synapseutils to help migrate files in Synapse projects and folders between AWS S3 buckets in the same region. More details on using these utilities can be found here.
This version supports login programatically and from the command line using personal access tokens that can be obtained from your synapse.org Settings. Additional documentation on login and be found here.
# programmatic syn = synapseclient.login(authToken=<token>)
# command line synapse login -p <token>
The location where downloaded entities are cached can be customized to a location other than the user’s home directory. This is useful in environments where writing to a home directory is not appropriate (e.g. an AWS lambda).
syn = synapseclient.Synapse(cache_root_dir=<directory path>)
A helper method on the Synapse object has been added to enable obtaining the Synapse certification quiz status of a user.
passed = syn.is_certified(<username or user_id>)
This version has been tested with Python 3.9.
Bug Fixes
[SYNPY-1039] - tableQuery asDataFrame() results with TYPE_LIST columns should be lists and not literal strings
[SYNPY-1109] - unparseable synapse cacheMap raises JSONDecodeError
[SYNPY-1110] - Cleanup on Windows console login
[SYNPY-1112] - Concurrent migration of entities sharing the same file handle can result in an error
[SYNPY-1114] - Mitigate new Rust compiler dependency on Linux via transitive cryptography dependency
[SYNPY-1118] - Migration tool erroring when it shouldn’t
New Features
[SYNPY-1058] - Accept oauth access token for authentication to use Synapse REST services
[SYNPY-1103] - Multipart copy integration
[SYNPY-1111] - Add function to get user certification status
Improvements
[SYNPY-885] - Public interface to customize CACHE_ROOT_DIR
[SYNPY-1102] - syncToSynapse adds empty annotation values
[SYNPY-1104] - Python 3.9 support
[SYNPY-1119] - Add source storage location option to storage migrate functions
2.2.2 (2020-10-18)
Highlights
This version addresses an issue with downloads being retried unsuccessfully after encountering certain types of errors.
A create_snapshot_version function is added for making table and view snapshots.
Bug Fixes
[SYNPY-1096] - Fix link to Synapse on PyPI
[SYNPY-1097] - downloaded files are reset when disk space exhausted
New Features
[SYNPY-1041] - Snapshot feature and programmatic clients
Improvements
[SYNPY-1063] - Consolidate builds to GitHub Actions
[SYNPY-1099] - Replace usage of deprecated PUT /entity/{id}/version endpoint
2.2.0 (2020-08-31)
Highlights
Files that are part of syncFromSynapse and syncToSynapse operations (
synapse get -r
andsynapse sync
in the command line client, respectively) are transferred in in parallel threads rather than serially, substantially improving the performance of these operations.Table metadata from synapse get -q is automatically downloaded to a users working directory instead of to the Synapse cache (a hidden folder).
Users can now pass their API key to synapse login in place of a password.
Bug Fixes
[SYNPY-1082] - Downloading entity linked to URL fails: module ‘urllib.parse’ has no attribute ‘urlretrieve’
Improvements
[SYNPY-1072] - Improve throughput of multiple small file transfers
[SYNPY-1073] - Parellelize upload syncs
[SYNPY-1074] - Parallelize download syncs
[SYNPY-1084] - Allow anonymous usage for public APIs like GET /teamMembers/{id}
[SYNPY-1088] - Manifest is in cache with synapse get -q
[SYNPY-1090] - Command line client does not support apikey
Tasks
[SYNPY-1080] - Remove Versionable from SchemaBase
[SYNPY-1085] - Move to pytest testing framework
[SYNPY-1087] - Improve synapseclient installation instructions
2.1.1 (2020-07-10)
Highlights
This version includes a performance improvement for syncFromSynapse downloads of deep folder hierarchies to local filesystem locations outside of the Synapse cache.
Support is added for SubmissionViews that can be used to query and edit a set of submissions through table services.
from synapseclient import SubmissionViewSchema project = syn.get("syn123") evaluation_id = '9876543' view = syn.store(SubmissionViewSchema(name='My Submission View', parent=project, scopes=[evaluation_id])) view_table = syn.tableQuery(f"select * from {view.id}")
Bug Fixes
[SYNPY-1075] - Error in Python test (submission annotations)
[SYNPY-1076] - Upgrade/fix Pandas dependency
Improvements
[SYNPY-1070] - Add support for submission views
[SYNPY-1078] - Improve syncFromSynapse performance for large folder structures synced to external paths
2.1.0 (2020-06-16)
Highlights
A
max_threads
property of the Synapse object has been added to customize the number of concurrent threads that will be used during file transfers.import synapseclient syn = synapseclient.login() syn.max_threads = 20
If not customized the default value is (CPU count + 4). Adjusting this value higher may speed up file transfers if the local system resources can take advantage of the higher setting. Currently this value applies only to files whose underlying storage is AWS S3.
Alternately, a value can be stored in the synapseConfig configuration file that will automatically apply as the default if a value is not explicitly set.
[transfer] max_threads=16
This release includes support for directly accessing S3 storage locations using AWS Security Token Service credentials. This allows use of external AWS clients and libraries with Synapse storage, and can be used to accelerate file transfers under certain conditions. To create an STS enabled folder and set-up direct access to S3 storage, see here.
The
getAnnotations
andsetAnnotations
methods of the Synapse object have been deprecated in favor of newerget_annotations
andset_annotations
methods, respectively. The newer versions are parameterized with a typedAnnotations
dictionary rather than a plain Python dictionary to prevent existing annotations from being accidentally overwritten. The expected usage for setting annotations is to first retrieve the existingAnnotations
for an entity before saving changes by passing back a modified value.annos = syn.get_annotations('syn123') # set key 'foo' to have value of 'bar' and 'baz' annos['foo'] = ['bar', 'baz'] # single values will automatically be wrapped in a list once stored annos['qwerty'] = 'asdf' annos = syn.set_annotations(annos)
The deprecated annotations methods may be removed in a future release.
A full list of issues addressed in this release are below.
Bug Fixes
[SYNPY-913] - Travis Build badge for develop branch is pointing to pull request
[SYNPY-960] - AppVeyor build badge appears to be failed while the builds are passed
[SYNPY-1036] - different users storing same file to same folder results in 403
[SYNPY-1056] - syn.getSubmissions fails due to new Annotation class in v2.1.0-rc
Improvements
[SYNPY-1036] - Make upload speeds comparable to those of the AWS S3 CLI
[SYNPY-1049] - Expose STS-related APIs
Tasks
[SYNPY-1059] - Use collections.abc instead of collections
2.0.0 (2020-03-23)
Python 2 is no longer supported as of this release. This release requires Python 3.6+.
Highlights:
Multi-threaded download of files from Synapse can be enabled by setting
syn.multi_threaded
toTrue
on asynapseclient.Synapse
object. This will become the default implementation in the future, but to ensure stability for the first release of this feature, it must be intentionally enabled.import synapseclient syn = synapseclient.login() syn.multi_threaded = True # syn123 now will be downloaded via the multi-threaded implementation syn.get("syn123")
Currently, multi-threaded download only works with files stored in AWS S3, where most files on Synapse reside. This also includes custom storage locations that point to an AWS S3 bucket. Files not stored in S3 will fall back to single-threaded download even if
syn.multi_threaded==True
.synapseutils.copy()
now has limitations on what can be copied:A user must have download permissions on the entity they want to copy.
Users cannot copy any entities that have access requirements.
contentTypes
andfileNames
are optional parameters insynapseutils.copyFileHandles()
Synapse Docker Repository(
synapseclient.DockerRepository
) objects can now be submitted to Synapse evaluation queues using theentity
argument insynapseclient.Synapse.submit()
. An optional argumentdocker_tag="latest"
has also been added tosynapseclient.Synapse.submit()
” to designate which tagged Docker image to submit.
A full list of issues addressed in this release are below.
Bugs Fixes
[SYNPY-271] - cache.remove fails to return the file handles we removed
[SYNPY-1032] - Support new columnTypes defined in backend
Tasks
[SYNPY-999] - Remove unsafe copy functions from client
[SYNPY-1027] - Copy function should copy things when users are part of a Team that has DOWNLOAD access
Improvements
[SYNPY-389] - submission of Docker repository
[SYNPY-537] - synapseutils.copyFileHandles requires fields that does not require at rest
[SYNPY-680] - synapseutils.changeFileMetaData() needs description in documentation
[SYNPY-682] - improve download speeds to be comparable to AWS
[SYNPY-807] - Drop support for Python 2
[SYNPY-907] - Replace `from <module> import …` with `import <module>`
[SYNPY-962] - remove ‘password’ as an option in default synapse config file
[SYNPY-972] - Link on Synapse Python Client Documentation points back at itself
1.9.4 (2019-06-28)
Bug Fixes
[SYNPY-881] - Synu.copy fails when copying a file with READ permissions
[SYNPY-888] - Docker repositories cannot be copied
[SYNPY-927] - trying to create a project with name that already exists hangs
[SYNPY-1005] - cli docs missing sub-commands
[SYNPY-1018] - Synu.copy shouldn’t copy any files with access restrictions
New Features
[SYNPY-851] - invite user or list of users to a team
Improvements
[SYNPY-608] - Add how to contribute md to github project
[SYNPY-735] - command line for building a table
[SYNPY-864] - docstring for the command line client doesn’t have complete list of sub-commands available
[SYNPY-926] - allow forceVersion false for command line client
[SYNPY-1013] - Documentation of “store” command for Synapse command line client
[SYNPY-1021] - change email contact for code of conduct
1.9.3 (2019-06-28)
Bug Fixes
1.9.2 (2019-02-15)
In version 1.9.2, we improved Views’ usability by exposing set_entity_types() function to change the entity types that will show up in a View:
import synapseclient
from synapseclient.table import EntityViewType
syn = synapseclient.login()
view = syn.get("syn12345")
view.set_entity_types([EntityViewType.FILE, EntityViewType.FOLDER])
view = syn.store(view)
Features
[SYNPY-919] - Expose a way to update entity types in a view using EntityViewType
Bug Fixes
Tasks
Improvements
1.9.1 (2019-01-20)
In version 1.9.1, we fix various bugs and added two new features:
Python 3.7 is supported.
Deprecation warnings are visible by default.
Features
Bug Fixes
[SYNPY-454] - Some integration tests do not clean up after themselves
[SYNPY-456] - Problems with updated query system
[SYNPY-515] - sphinx documentation not showing for some new classes
[SYNPY-526] - deprecate downloadTableFile()
[SYNPY-578] - switch away from POST /entity/#/table/deleterows
[SYNPY-594] - Getting error from dev branch in integration test against staging
[SYNPY-796] - fix or remove PyPI downloads badge in readme
[SYNPY-799] - Unstable test: Test PartialRow updates to entity views from rowset queries
[SYNPY-846] - error if password stored in config file contains a ‘%’
Tasks
[SYNPY-491] - Figure out custom release note fitlers
[SYNPY-840] - Install not working on latest python
[SYNPY-847] - uploadFileHandle should not be deprecated nor removed
[SYNPY-852] - Check and update help.synapse.org to reflect the change in the Python client
[SYNPY-860] - vignette for how to upload a new version of a file directly to a synapse entity
[SYNPY-863] - Update public documentation to move away from the query services
[SYNPY-866] - Update Synapse logo in Python docs :)
[SYNPY-873] - consolidate integration testing to platform dev account
Improvements
[SYNPY-473] - Change syn.list to no longer use deprecated function chunkedQuery
[SYNPY-573] - synapse list command line shouldn’t list the parent container
[SYNPY-581] - <entity>.annotations return object is inconsistent with getAnnotations()
[SYNPY-612] - Rename view_type to viewType in EntityViewSchema for consistency
[SYNPY-777] - Python client _list still uses chunckedQuery and result seem out of date
[SYNPY-804] - Update styling in the python docs to more closely match the Docs site styling
[SYNPY-815] - Update the build to use test user instead of migrationAdmin
[SYNPY-848] - remove outdated link to confluence for command line query
[SYNPY-856] - build_table example in the docs does not look right
[SYNPY-858] - Write file view documentation in python client that is similar to synapser
[SYNPY-870] - Submitting to an evaluation queue can’t accept team as int
1.9.0 (2018-09-28)
In version 1.9.0, we deprecated and removed query() and chunkedQuery(). These functions used the old query services which does not perform well. To query for entities filter by annotations, please use EntityViewSchema.
We also deprecated the following functions and will remove them in Synapse Python client version 2.0. In the Activity object:
usedEntity()
usedURL()
In the Synapse object:
getEntity()
loadEntity()
createEntity()
updateEntity()
deleteEntity()
downloadEntity()
uploadFile()
uploadFileHandle()
uploadSynapseManagedFileHandle()
downloadTableFile()
Please see our documentation for more details on how to migrate your code away from these functions.
Features
SYNPY-806 - Support Folders and Tables in View
Bug Fixes
SYNPY-195 - Dangerous exception handling
SYNPY-261 - error downloading data from synapse (python client)
SYNPY-694 - Uninformative error in copyWiki function
SYNPY-805 - Uninformative error when getting View that does not exist
SYNPY-819 - command-line clients need to be updated to replace the EntityView ‘viewType’ with ‘viewTypeMask’
Tasks
Improvements
1.8.2 (2018-08-17)
In this release, we have been performed some house-keeping on the code base. The two major changes are:
making syn.move() available to move an entity to a new parent in Synapse. For example:
import synapseclient from synapseclient import Folder syn = synapseclient.login() file = syn.get("syn123") folder = Folder("new folder", parent="syn456") folder = syn.store(folder) # moving file to the newly created folder syn.move(file, folder)exposing the ability to use the Synapse Python client with single threaded. This feature is useful when running Python script in an environment that does not support multi-threading. However, this will negatively impact upload speed. To use single threaded:
import synapseclient synapseclient.config.single_threaded = True
Bug Fixes
SYNPY-535 - Synapse Table update: Connection Reset
SYNPY-603 - Python client and synapser cannot handle table column type LINK
SYNPY-688 - Recursive get (sync) broken for empty folders.
SYNPY-744 - KeyError when trying to download using Synapse Client 1.8.1
SYNPY-750 - Error in downloadTableColumns for file view
SYNPY-758 - docs in Sphinx don’t show for synapseclient.table.RowSet
SYNPY-760 - Keyring related error on Linux
SYNPY-766 - as_table_columns() returns a list of columns out of order for python 3.5 and 2.7
SYNPY-776 - Cannot log in to Synapse - error(54, ‘Connection reset by peer’)
SYNPY-795 - Not recognizable column in query result
Features
Tasks
Improvements
1.8.1 (2018-05-17)
This release is a hotfix for a bug. Please refer to 1.8.0 release notes for information about additional changes.
Bug Fixes
SYNPY-706 - syn.username can cause attribute not found if user not logged in
1.8.0 (2018-05-07)
This release has 2 major changes:
The client will no longer store your saved credentials in your synapse cache (~/synapseCache/.session). The python client now relies on keyring to handle credential storage of your Synapse credentials.
The client also now uses connection pooling, which means that all method calls that connect to Synapse should now be faster.
The remaining changes are bug fixes and cleanup of test code.
Below are the full list of issues addressed by this release:
Bug Fixes
Tasks
Improvements
1.7.5 (2018-01-31)
v1.7.4 release was broken for new users that installed from pip. v1.7.5 has the same changes as v1.7.4 but fixes the pip installation.
1.7.4 (2018-01-29)
- This release mostly includes bugfixes and improvements for various Table classes:
Fixed bug where you couldn’t store a table converted to a pandas.Dataframe if it had a INTEGER column with some missing values.
EntityViewSchema can now automatically add all annotations within your defined scopes as columns. Just set the view’s addAnnotationColumns=True before calling syn.store(). This attribute defaults to True for all newly created EntityViewSchemas. Setting addAnnotationColumns=True on existing tables will only add annotation columns that are not already a part of your schema.
You can now use synapseutils.notifyMe as a decorator to notify you by email when your function has completed. You will also be notified of any Errors if they are thrown while your function runs.
- We also added some new features:
syn.findEntityId() function that allows you to find an Entity by its name and parentId, set parentId to None to search for Projects by name.
The bulk upload functionality of synapseutils.syncToSynapse is available from the command line using: synapse sync.
Below are the full list of issues addressed by this release:
Features
Improvements
SYNPY-267 - Update Synapse tables for integer types
SYNPY-304 - Table objects should implement len()
SYNPY-416 - warning message for recursive get when a non-Project of Folder entity is passed
SYNPY-482 - Create a sample synapseConfig if none is present
SYNPY-489 - Add a boolean parameter in EntityViewSchema that will indicate whether the client should create columns based on annotations in the specified scopes
SYNPY-494 - Link should be able to take an entity object as the parameter and derive its id
SYNPY-511 - improve exception handling
SYNPY-512 - Remove the use of PaginatedResult’s totalNumberOfResult
SYNPY-539 - When creating table Schemas, enforce a limit on the number of columns that can be created.
Bug Fixes
SYNPY-235 - can’t print Row objects with dates in them
SYNPY-272 - bug syn.storing rowsets containing Python datetime objects
SYNPY-297 - as_table_columns shouldn’t give fractional max size
SYNPY-404 - when we get a SynapseMd5MismatchError we should delete the downloaded file
SYNPY-425 - onweb doesn’t work for tables
SYNPY-438 - Need to change ‘submit’ not to use evaluation/id/accessRequirementUnfulfilled
SYNPY-496 - monitor.NotifyMe can not be used as an annotation decorator
SYNPY-521 - inconsistent error message when username/password is wrong on login
SYNPY-536 - pre-signed upload URL expired warnings using Python client sync function
SYNPY-555 - EntityViewSchema is missing from sphinx documentation
SYNPY-558 - synapseutils.sync.syncFromSynapse throws error when syncing a Table object
SYNPY-595 - Get recursive folders filled with Links fails
SYNPY-605 - Update documentation for getUserProfile to include information about refreshing and memoization
Tasks
1.7.3 (2017-12-08)
Release 1.7.3 introduces fixes and quality of life changes to Tables and synapseutils:
Changes to Tables:
You no longer have to include the etag column in your SQL query when using a tableQuery() to update File/Project Views. just SELECT the relevant columns and etags will be resolved automatically.
The new PartialRowSet class allows you to only have to upload changes to individual cells of a table instead of every row that had a value changed. It is recommended to use the PartialRowSet.from_mapping() classmethod instead of the PartialRowSet constructor.
Changes to synapseutils:
Improved documentation
You can now use ~ to refer to your home directory in your manifest.tsv
We also added improved debug logging and use Python’s builtin logging module instead of printing directly to sys.stderr
Below are the full list of issues addressed by this release:
Bug Fixes
SYNPY-419 - support object store from client
SYNPY-499 - metadata manifest file name spelled wrong
SYNPY-504 - downloadTableFile changed return type with no change in documentation or mention in release notes
SYNPY-508 - syncToSynapse does not work if “the file path in “used” or “executed” of the manifest.tsv uses home directory shortcut “~”
SYNPY-516 - synapse sync file does not work if file is a URL
SYNPY-525 - Download CSV file of Synapse Table - 416 error
SYNPY-572 - Users should only be prompted for updates if the first or second part of the version number is changed.
Features
Tasks
SYNPY-569 - ‘includeEntityEtag’ should be True for Async table csv query downloads
Improvements
1.7.1 (2017-11-17)
Release 1.7 is a large bugfix release with several new features. The main ones include:
We have expanded the synapseutils packages to add the ability to:
Bulk upload files to synapse (synapseutils.syncToSynapse).
Notify you via email on the progress of a function (useful for jobs like large file uploads that may take a long time to complete).
The syncFromSynapse function now creates a “manifest” which contains the metadata of downloaded files. (These can also be used to update metadata with the bulk upload function.
File View tables can now be created from the python client using EntityViewSchema. See fileviews documentation.
The python client is now able to upload to user owned S3 Buckets. Click here for instructions on linking your S3 bucket to synapse.
We’ve also made various improvements to existing features:
The LARGETEXT type is now supported in Tables allowing for strings up to 2Mb.
The –description argument when creating/updating entities from the command line client will now create a Wiki for that entity. You can also use –descriptionFile to write the contents of a markdown file as the entity’s Wiki
Two member variables of the File object, file_entity.cacheDir and file_entity.files is being DEPRECATED in favor of file_entity.path for finding the location of a downloaded File
pandas dataframe`s containing `datetime values can now be properly converted into csv and uploaded to Synapse.
We also added a optional convert_to_datetime parameter to CsvFileTable.asDataFrame() that will automatically convert Synapse DATE columns into datetime objects instead of leaving them as long unix timestamps
Below are the full list of bugs and issues addressed by this release:
Features
SYNPY-53 - support syn.get of external FTP links in py client
SYNPY-179 - Upload to user owned S3 bucket
SYNPY-412 - allow query-based download based on view tables from command line client
SYNPY-487 - Add remote monitoring of long running processes
SYNPY-415 - Add Docker and TableViews into Entity.py
SYNPY-89 - Python client: Bulk upload client/command
SYNPY-413 - Update table views via python client
SYNPY-301 - change actual file name from python client
SYNPY-442 - set config file path on command line
Improvements
SYNPY-407 - support LARGETEXT in tables
SYNPY-360 - Duplicate file handles are removed from BulkFileDownloadRequest
SYNPY-187 - Move –description in command line client to create wikis
SYNPY-224 - When uploading to a managed external file handle (e.g. SFTP), fill in storageLocationId
SYNPY-315 - Default behavior for files in cache dir should be replace
SYNPY-381 - Remove references to “files” and “cacheDir”.
SYNPY-396 - Create filehandle copies in synapseutils.copy instead of downloading
SYNPY-403 - Use single endpoint for all downloads
SYNPY-435 - Convenience function for new service to get entity’s children
SYNPY-471 - docs aren’t generated for synapseutils
SYNPY-472 - References to wrong doc site
SYNPY-347 - Missing dtypes in table.DTYPE_2_TABLETYPE
SYNPY-463 - When copying filehandles we should add the files to the cache if we already donwloaded them
SYNPY-475 - Store Tables timeout error
Bug Fixes
SYNPY-190 - syn.login(‘asdfasdfasdf’) should fail
SYNPY-344 - weird cache directories
SYNPY-346 - ValueError: cannot insert ROW_ID, already exists in CsvTableFile constructor
SYNPY-351 - Versioning broken for sftp files
SYNPY-366 - file URLs leads to wrong path
SYNPY-393 - New cacheDir causes cache to be ignored(?)
SYNPY-409 - Python client cannot depend on parsing Amazon pre-signed URLs
SYNPY-418 - Integration test failure against 167
SYNPY-421 - syn.getWikiHeaders has a return limit of 50 (Need to return all headers)
SYNPY-423 - upload rate is off or incorrect
SYNPY-424 - File entities don’t handle local_state correctly for setting datafilehandleid
SYNPY-426 - multiple tests failing because of filenameOveride
SYNPY-427 - test dependent on config file
SYNPY-428 - sync function error
SYNPY-431 - download ending early and not restarting from previous spot
SYNPY-443 - tests/integration/integration_test_Entity.py:test_get_with_downloadLocation_and_ifcollision AssertionError
SYNPY-461 - On Windows, command line client login credential prompt fails (python 2.7)
SYNPY-465 - Update tests that set permissions to also include ‘DOWNLOAD’ permission and tests that test functions using queries
SYNPY-468 - Command line client incompatible with cache changes
SYNPY-470 - default should be read, download for setPermissions
SYNPY-483 - integration test fails for most users
SYNPY-484 - URL expires after retries
SYNPY-486 - Error in integration tests
SYNPY-488 - sync tests for command line client puts file in working directory
SYNPY-142 - PY: Error in login with rememberMe=True
SYNPY-464 - synapse get syn4988808 KeyError: u’preSignedURL’
Tasks
1.6.1 (2016-11-02)
What is New
In version 1.6 we introduce a new sub-module _synapseutils_ that provide convenience functions for more complicated operations in Synapse such as copying of files wikis and folders. In addition we have introduced several improvements in downloading content from Synapse. As with uploads we are now able to recover from an interrupted download and will retry on network failures.
Improvements
We have improved download robustness and error checking, along with extensive recovery on failed operations. This includes the ability for the client to pause operation when Synapse is updated.
SYNPY-270 - Synapse READ ONLY mode should cause pause in execution
SYNPY-308 - Add md5 checking after downloading a new file handle
SYNPY-309 - Add download recovery by using the ‘Range’: ‘bytes=xxx-xxx’ header
SYNPY-353 - Speed up downloads of fast connections
SYNPY-356 - Add support for version flag in synapse cat command line
SYNPY-357 - Remove failure message on retry in multipart_upload
SYNPY-380 - Add speed meter to downloads/uploads
SYNPY-387 - Do exponential backoff on 429 status and print explanatory error message from server
SYNPY-390 - Move recursive download to Python client utils
Bug Fixes
SYNPY-154 - 500 Server Error when storing new version of file from command line
SYNPY-168 - Failure on login gives an ugly error message
SYNPY-253 - Error messages on upload retry inconsistent with behavior
SYNPY-261 - error downloading data from synapse (python client)
SYNPY-274 - Trying to use the client without logging in needs to give a reasonable error
SYNPY-331 - test_command_get_recursive_and_query occasionally fails
SYNPY-337 - Download error on 10 Gb file.
SYNPY-343 - Login failure
SYNPY-351 - Versioning broken for sftp files
SYNPY-352 - file upload max retries exceeded messages
SYNPY-358 - upload failure from python client (threading)
SYNPY-361 - file download fails midway without warning/error
SYNPY-362 - setAnnotations bug when given synapse ID
SYNPY-363 - problems using provenance during upload
SYNPY-382 - Python client is truncating the entity id in download csv from table
SYNPY-383 - Travis failing with paramiko.ssh_exception.SSHException: No hostkey
SYNPY-384 - resuming a download after a ChunkedEncodingError created new file with correct size
SYNPY-388 - Asynchronous creation of Team causes sporadic test failure
SYNPY-391 - downloadTableColumns() function doesn’t work when resultsAs=rowset is set for for syn.tableQuery()
SYNPY-397 - Error in syncFromSynapse() integration test on Windows
SYNPY-399 - python client not compatible with newly released Pandas 0.19


While it is perfectly possible to write a song with only I, IV, and V, most songs do not limit themselves to these chords. One problem is that, as alluded to in Chapter 1, I, IV, and V are all major chords. This lack of variety means that the range of emotions that one can evoke is somewhat limited. One obvious way to make things more interesting is to include a minor chord in the mix, but which one to choose? Recall that the basic chords consist of the following:
That means our choices for minor chords are ii, iii, and vi.
While ii and iii are both minor chords that would fit the bill, vi is significantly more common. vi is very versatile and can be used in many situations without sounding awkward. It can be used after I and sounds great before or after IV, and V, for example. We’ll learn how ii and iii are used in Chapter 4.
Let’s listen to the chords from “Don’t Stop Believing” by Journey to see how it incorporates the vi. Concentrate on the third chord (the vi) to get a feel for how vi sounds.
This particular progression (I → V → vi → IV) is popular across many genres of popular music and shows up again and again. It has been used in so many songs that people have taken notice. Below are a few songs that have used this progression.
Keep in mind that these songs are not all in the same key and would seem to use different chords if you were to purchase their sheet music or guitar tab. Relative notation, however, makes it easy to see that they all use the same progression.
Lastly, the message to take away from this video is not “all I need to be a pop star is this magical progression!” If your entire song only consisted of these four chords repeated over and over again in this order, it wouldn’t be very interesting. That’s why the songs from the previous example usually don’t rely exclusively on this progression. Other parts of the songs use different chords that complement the I → V → vi → IV so they don’t get old.


Sign in to your account
Create a new account
Enter Information:
Footer Information
Enter Information:
Footer Information
Enter Information:
Footer Information
Enter Information:
Footer Information
Enter Information:
Footer Information
Welcome, {{ user.username }}!


Events
jsPlumb supports binding to several different events on Connections, Endpoints and Overlays, and also on the jsPlumb object itself.
jsPlumb Events
To bind an to event on jsPlumb itself (or a jsPlumb instance), use jsPlumb.bind(event, callback)
:
jsPlumb.bind("connection", function(info) {
.. update your model in here, maybe.
});
These are the events you can bind to on the jsPlumb class:
connection(info, originalEvent)
Notification a Connection was established.
info
is an object with the following properties:
- connection - the new Connection. you can register listeners on this etc.
- sourceId - id of the source element in the Connection
- targetId - id of the target element in the Connection
- source - the source element in the Connection
- target - the target element in the Connection
- sourceEndpoint - the source Endpoint in the Connection
- targetEndpoint - the targetEndpoint in the Connection
Note: jsPlumb.connect
causes this event
to be fired, but there is of course no original event when a connection
is established programmatically. So you can test to see if originalEvent
is undefined to determine whether a connection was estblished using the mouse or not.
All of the source/target properties are actually available inside the
Connection object, but - for one of those rubbish historical reasons -
are provided separately because of a vagary of the connectionDetached
callback, which is discussed below.
connectionDetached(info, originalEvent)
Notification a Connection was detached.
As with connection
, the first argument to the callback is an object with the following properties:
- connection - the Connection that was detached.
- sourceId - id of the source element in the Connection before it was detached
- targetId - id of the target element in the Connection before it was detached
- source - the source element in the Connection before it was detached
- target - the target element in the Connection before it was detached
- sourceEndpoint - the source Endpoint in the Connection before it was detached
- targetEndpoint - the targetEndpoint in the Connection before it was detached
In the event that the Connection was new and had never been established between two Endpoints, it has a pending
flag set on it.
The source
/target
properties are provided
separately from the Connection, because this event is fired whenever a
Connection is either detached and abandoned, or detached from some
Endpoint and attached to another. In the latter case, the Connection
that is passed to this callback is in an indeterminate state (that is,
the Endpoints are still in the state they are in when dragging, and do
not reflect static reality), and so the source
/target
properties give you the real story.
The second argument is the original mouse event that caused the disconnection, if any.
connectionMoved(info, originalEvent)
Notification that an existing connection's source or target endpoint was dragged to some new location. info
contains the following properties:
- index - 0 for source endpoint, 1 for target endpoint
- originalSourceId - id of connection source element before move
- newSourceId - id of connection source element after move
- originalTargetId id of connection target before move
- newTargetId - id of connection target after move
- originalSourceEndpoint - source endpoint before move
- newSourceEndpoint - source endpoint after move
- originalTargetEndpoint - target endpoint before move
- newTargetEndpoint - target endpoint after move
connectionDrag(connection)
Notification an existing Connection is being dragged. Note that when this event fires for a brand new Connection, the target of the Connection is a transient element that jsPlumb is using for dragging, and will be removed from the DOM when the Connection is subsequently either established or aborted.
connectionDragStop(connection)
Notification a Connection drag has stopped. This is only fired for existing Connections.
click(connection, originalEvent)
Notification a Connection was clicked.
dblclick(connection, originalEvent)
Notification a Connection was double-clicked.
endpointClick(endpoint, originalEvent)
Notification an Endpoint was clicked.
endpointDblClick(endpoint, originalEvent)
Notification an Endpoint was double-clicked.
contextmenu(component, originalEvent)
A right-click on some given component. jsPlumb will report right clicks on both Connections and Endpoints.
beforeDrop(info)
This event is fired when a new or existing connection has been dropped. info
contains the following properties:
- sourceId - the id of the source element in the connection
- targetId - the id of the target element in the connection
- scope - the scope of the connection
- connection - the actual
Connection object. You can access the 'endpoints' array in a Connection
to get the Endpoints involved in the Connection, but be aware that when
a Connection is being dragged, one of these Endpoints will always be a
transient Endpoint that exists only for the life of the drag. To get the
Endpoint on which the Connection is being dropped, use the
dropEndpoint
member. - dropEndpoint - this is the actual Endpoint on which the Connection is being dropped. This may be null, because it will not be set if the Connection is being dropped on an element on which makeTarget has been called.
If you return false (or nothing) from this callback, the new Connection is aborted and removed from the UI.
beforeDetach(connection)
This event is fired when a Connection is about to be detached, for whatever reason. Your callback function is passed the Connection that the user has just detached. Returning false from this interceptor aborts the Connection detach.
Connection Events
To bind to an event on a Connection, you also use the bind
method:
var connection = jsPlumb.connect({source:"d1", target:"d2"});
connection.bind("click", function(conn) {
console.log("you clicked on ", conn);
});
These are the Connection events to which you can bind a listener:
click(connection, originalEvent)
- notification a Connection was clicked.dblclick(connection, originalEvent)
- notification a Connection was double-clicked.contextmenu(connection, originalEvent)
- a right-click on the Connection.mouseenter(connection, originalEvent)
- notification the mouse entered the Connection's path.mouseexit(connection, originalEvent)
- notification the mouse exited the Connection's path.mousedown(connection, originalEvent)
- notification the mouse button was pressed on the Connection's path.mouseup(connection, originalEvent)
- notification the mouse button was released on the Connection's path.
Endpoint Events
To bind to an event on a Endpoint, you again use the bind
method:
var endpoint = jsPlumb.addEndpoint("d1", { someOptions } );
endpoint.bind("click", function(endpoint) {
console.log("you clicked on ", endpoint);
});
These are the Endpoint events to which you can bind a listener:
click(endpoint, originalEvent)
- notification an Endpoint was clicked.dblclick(endpoint, originalEvent)
- notification an Endpoint was double-clicked.contextmenu(endpoint, originalEvent)
- a right-click on the Endpoint.mouseenter(endpoint, originalEvent)
- notification the mouse entered the Endpoint.mouseexit(endpoint, originalEvent)
- notification the mouse exited the Endpoint.mousedown(endpoint, originalEvent)
- notification the mouse button was pressed on the Endpoint.mouseup(endpoint, originalEvent)
- notification the mouse button was released on the Endpoint.maxConnections(info, originalEvent)
- notification the user tried to drop a Connection on an Endpoint that already has the maximum number of Connections.info
is an object literal containing these values:- endpoint : Endpoint on which the Connection was dropped
- connection : The Connection the user tried to drop
- maxConnections : The value of
maxConnections
for the Endpoint
Overlay Events
Registering event listeners on an Overlay is a slightly different procedure - you provide them as arguments to the Overlay's constructor. This is because you never actually act on an Overlay object.
Here's how to register a click listener on an Overlay:
jsPlumb.connect({
source:"el1",
target:"el2",
overlays:[
[ "Label", {
events:{
click:function(labelOverlay, originalEvent) {
console.log("click on label overlay for :" + labelOverlay.component);
}
}
}],
[ "Diamond", {
events:{
dblclick:function(diamondOverlay, originalEvent) {
console.log("double click on diamond overlay for : " + diamondOverlay.component);
}
}
}]
]
});
The related component for an Overlay is available to you as the component
member of the Overlay.
Note that events registered on Diamond, Arrow or PlainArrow overlays will not fire with the Canvas renderer - they work only with the SVG and VML renderers.
Unbinding Events
On the jsPlumb object and on Connections and Endpoints, you can use the unbind
method to remove a listener. This method either takes the name of the event to unbind:
jsPlumb.unbind("click");
...or no argument, meaning unbind all events:
var e = jsPlumb.addEndpoint("someDiv");
e.bind("click", function() { ... });
e.bind("dblclick", function() { ... });
...
e.unbind("click");


This page is about me!
|
Name: Alfred E Neuman |
I am interested in many things and how they work. My main hobbies are:
I am also interested in pursuing a career in the Electronics Arts sectors, and although I cannot draw well, I am able to use the laptop to change and manipulate images and videos.
All these skills are self-taught.


Mergesort
This exercise is taken from Conor McBride's tutorial on Epigram
Sorting
First, specify sorting lists of natural numbers through a predicate :
sort : list nat -> list nat -> Prop.
Merging
Define a function merge: list nat -> list nat -> list nat
such that the following lemma holds :
Lemma merge_and_sort : forall l l', sorted l -> sorted l' ->
sort (l++l') (merge l l').
Prove this property.

We now consider trees whose nodes contain boolean values and leaves
an optional value of type L, i.e trees of type
tree bool (option L).
Complete the following definition:
(* A (bool,option L) tree is balanced if every node labeled with true has
the same number of leaves labeled with L in both subtrees, and every
node labeled with false has one more leave labeled with L in its left son
than its right son *)
Inductive balanced(L:Type): tree bool (option L) -> nat -> Prop :=
Insertion in a balanced tree
Define a function :
insert (L:Type): L -> tree bool (option L)) -> tree bool (option L)
such that the insertion of l:L into a balanced tree ressults in
a balanced tree
Building a balanced tree from a list
Define a function
share (L:Type) : L -> tree bool (option L)
such that share _ ls returns a balanced tree contianing all the
elements of ls
mergesort itself
We now have all material for building a sorting function
mergesort : list nat -> list nat
- let l be a list of natural numbers
- build a balanced tree whose leaves are labled with the elements of
l
- flatten this tree, using merge> to combine the leaves of
the left and right subtrees
Prove the theorem:
Theorem mergesort_ok : forall l, sort l (mergesort l).
Solution
Follow this link
Going home


Some versions of tftp are run interactively, like this:
$ tftp <IP_ADDRESS>
tftp> get myfile.txt
If we can't run it interactively, for whatever reason, we can do this trick
tftp <IP_ADDRESS> <<< "get shell5555.php shell5555.php"


--- layout: default title: Gallery prpatil: - image_path: /img/gallery/1.jpg - image_path: /img/gallery/2.jpg - image_path: /img/gallery/3.jpg - image_path: /img/gallery/4.jpg - image_path: /img/gallery/5.jpg - image_path: /img/gallery/6.jpg - image_path: /img/gallery/7.jpg - image_path: /img/gallery/8.jpg - image_path: /img/gallery/9.jpg pdpoly: - image_path: /img/gallery/pd1.jpg - image_path: /img/gallery/pd2.jpg - image_path: /img/gallery/pd3.jpg --- P. R. Patil College of Engineering & Technology Workshop - 23rd & 24th Jan, 2016 {% for item in page.prpatil %} {% endfor %} Dr. Punjabrao Deshmukh Polytechnic College Workshop - 6th & 7th Feb, 2016 {% for item in page.pdpoly %} {% endfor %}


--- layout: page title: About header-img: "img/about-bg.png" ---
My page will be about my ups and downs with coding and how I overcame the problems I faced.


Preparation time
1-2 hours
Cooking time
30 mins to 1 hour
Serves
Serves 4
This is a great recipe for a Saturday night feast with friends and family - get the kids involved making the chapatis.
For this recipe you will need a food processor.
Blend the chilli powder, cumin, garam masala, coriander, 3 garlic cloves, turmeric, cinnamon, ginger and cashews to a fine purée in a food processor. Add half of the lemon juice and blitz once more until smooth. Stir in the yoghurt until well combined.
Put the chicken breasts in a bowl and pour over the marinade, mixing to coat. Marinate in the fridge for 1 hour.
Preheat the grill to its highest setting and place an oven shelf in the middle of the oven.
Transfer the marinated chicken to a grill tray lined with aluminium foil. Grill for 12-15 minutes, until the marinade has browned and the chicken is just cooked through.
Meanwhile, heat the oil in a frying pan over a medium heat. Add the cinnamon stick and cardamom pods and stir-fry for 1 minute, until fragrant. Add the remaining garlic, chillies and tomatoes and simmer for 4-5 minutes.
Add the grilled chicken and cook for a further 4-5 minutes, until the sauce has thickened slightly and the chicken is cooked through.
Whisk in the chilled butter a little at a time, then add the cream and simmer for another 2 minutes. Season, to taste, with salt and freshly ground black pepper. Keep warm.
Meanwhile, make some chapatis, pile the flour onto a clean work surface and make a well in the centre. Gradually and carefully add 250ml/9fl oz cold water, pulling the flour in from the inner edges of the well to combine, until the mixture comes together as a soft dough. Knead until soft, smooth and elastic.
Divide the dough into 4 pieces then roll each piece into a ball.
Heat a griddle pan or non-stick frying pan over a high heat until very hot. Cook the chapatis one at a time until just charred, about 20 seconds on each side. When the chapati is cooked, bubbles will form at its surface. Brush the cooked chapatis with the melted butter.
Serve the butter chicken with the chapatis.


Background
A collection of classes to make styling your elements a breeze.
Colors
Easily change the background color of your elements using boba's refreshing palette.
| Colors | ||
To change the background color of an element, add a .bg-{COLOR} class. |
||
.bg-red |
Add this class to make the background of an element red. | My background is red! |
.bg-orange |
Add this class to make the background of an element orange. | My background is orange! |
.bg-yellow |
Add this class to make the background of an element yellow. | My background is yellow! |
.bg-green |
Add this class to make the background of an element green. | My background is green! |
.bg-teal |
Add this class to make the background of an element teal. | My background is teal! |
.bg-blue |
Add this class to make the background of an element blue. | My background is blue! |
.bg-indigo |
Add this class to make the background of an element indigo. | My background is indigo! |
.bg-purple |
Add this class to make the background of an element purple. | My background is purple! |
.bg-pink |
Add this class to make the background of an element pink. | My background is pink! |
.bg-dark |
Add this class to make the background of an element dark. | My background is dark! |
.bg-light |
Add this class to make the background of an element light. | My background is light! |
.bg-black |
Add this class to make the background of an element black. | My background is black! |
.bg-white |
Add this class to make the background of an element white. | My background is white! |
Tints
Use boba's tint colors to add a subtle splash of color to your components.
| Tints | ||
To change the background color of an element, add a .bg-tint-{COLOR} class. |
||
.bg-tint-red |
Add this class to make the background of an element tint-red. | My background is tint-red! |
.bg-tint-orange |
Add this class to make the background of an element tint-orange. | My background is tint-orange! |
.bg-tint-yellow |
Add this class to make the background of an element tint-yellow. | My background is tint-yellow! |
.bg-tint-green |
Add this class to make the background of an element tint-green. | My background is tint-green! |
.bg-tint-teal |
Add this class to make the background of an element tint-teal. | My background is tint-teal! |
.bg-tint-blue |
Add this class to make the background of an element tint-blue. | My background is tint-blue! |
.bg-tint-indigo |
Add this class to make the background of an element tint-indigo. | My background is tint-indigo! |
.bg-tint-purple |
Add this class to make the background of an element tint-purple. | My background is tint-purple! |
.bg-tint-pink |
Add this class to make the background of an element tint-pink. | My background is tint-pink! |
.bg-tint-dark |
Add this class to make the background of an element tint-dark. | My background is tint-dark! |
.bg-tint-light |
Add this class to make the background of an element tint-light. | My background is tint-light! |
Extended
Additional utilities to help you create the perfect background color.
Hover
For a more subtle effect, use the hover classes to change the background color of your element only when someone hovers/focuses on it.
| Hover | ||
To change the background color on hover, add a .bg-hover-{COLOR} class. |
||
.bg-hover-red |
Add this class to make the background of an element red on hover. | My background is red on hover! |
.bg-hover-orange |
Add this class to make the background of an element orange on hover. | My background is orange on hover! |
.bg-hover-yellow |
Add this class to make the background of an element yellow on hover. | My background is yellow on hover! |
.bg-hover-green |
Add this class to make the background of an element green on hover. | My background is green on hover! |
.bg-hover-teal |
Add this class to make the background of an element teal on hover. | My background is teal on hover! |
.bg-hover-blue |
Add this class to make the background of an element blue on hover. | My background is blue on hover! |
.bg-hover-indigo |
Add this class to make the background of an element indigo on hover. | My background is indigo on hover! |
.bg-hover-purple |
Add this class to make the background of an element purple on hover. | My background is purple on hover! |
.bg-hover-pink |
Add this class to make the background of an element pink on hover. | My background is pink on hover! |
.bg-hover-dark |
Add this class to make the background of an element dark on hover. | My background is dark on hover! |
.bg-hover-light |
Add this class to make the background of an element light on hover. | My background is light on hover! |
.bg-hover-black |
Add this class to make the background of an element black on hover. | My background is black on hover! |
.bg-hover-white |
Add this class to make the background of an element white on hover. | My background is white on hover! |
Active
For an even more subtle effect, use the active classes to change the background color of your element only when someone someone clicks on it.
| Active | ||
To change the background color when clicked, add a .bg-active-{COLOR} class. |
||
.bg-active-red |
Add this class to make the background of an element red when clicked. | My background is red when clicked! |
.bg-active-orange |
Add this class to make the background of an element orange when clicked. | My background is orange when clicked! |
.bg-active-yellow |
Add this class to make the background of an element yellow when clicked. | My background is yellow when clicked! |
.bg-active-green |
Add this class to make the background of an element green when clicked. | My background is green when clicked! |
.bg-active-teal |
Add this class to make the background of an element teal when clicked. | My background is teal when clicked! |
.bg-active-blue |
Add this class to make the background of an element blue when clicked. | My background is blue when clicked! |
.bg-active-indigo |
Add this class to make the background of an element indigo when clicked. | My background is indigo when clicked! |
.bg-active-purple |
Add this class to make the background of an element purple when clicked. | My background is purple when clicked! |
.bg-active-pink |
Add this class to make the background of an element pink when clicked. | My background is pink when clicked! |
.bg-hover-dark |
Add this class to make the background of an element dark when clicked. | My background is dark when clicked! |
.bg-hover-light |
Add this class to make the background of an element light when clicked. | My background is light when clicked! |
.bg-hover-black |
Add this class to make the background of an element black when clicked. | My background is black when clicked! |
.bg-hover-white |
Add this class to make the background of an element white when clicked. | My background is white when clicked! |
Combinations
Combine the various background helper classes to create the perfect element coloring.
<div class="bg-red bg-hover-green bg-active-blue"> Red, Hover-Green, Active-Blue </div>
Shades
Even more utilities to help you create the perfect background color.
Color Shades
Further fine-tune the color of your background by adjusting its shade.
| Color Shades | ||
|
To change the shade of your colored background, use the |
||
.lighten-bg-3 |
Add this class to make your background 3 shades lighter. | My red background uses lighten-bg-3! |
.lighten-bg-2 |
Add this class to make your background 2 shades lighter. | My red background uses lighten-bg-2! |
.lighten-bg-1 |
Add this class to make your background 1 shade lighter. | My red background uses lighten-bg-1! |
| Base Color | This is a default background using .bg-red for reference. |
I'm the default red background! |
.darken-bg-1 |
Add this class to make your background 1 shade darker. | My red background uses darken-bg-1! |
.darken-bg-2 |
Add this class to make your background 2 shades darker. | My red background uses darken-bg-2! |
.darken-bg-3 |
Add this class to make your background 3 shades darker. | My red background uses darken-bg-3! |
Hover Shades
Further fine-tune the color of your background on hover by adjusting its shade.
| Hover Shades | ||
|
To change the shade of your colored background on hover, use the |
||
.lighten-bg-hover-3 |
Add this class to make your background 3 shades lighter on hover. | My red background uses lighten-bg-hover-3! |
.lighten-bg-hover-2 |
Add this class to make your background 2 shades lighter on hover. | My red background uses lighten-bg-hover-2! |
.lighten-bg-hover-1 |
Add this class to make your background 1 shade lighter on hover. | My red background uses lighten-bg-hover-1! |
| Base Color | This is a default background using .bg-hover-red for reference. |
I'm the default red background! |
.darken-bg-hover-1 |
Add this class to make your background 1 shade darker on hover. | My red background uses darken-bg-hover-1! |
.darken-bg-hover-2 |
Add this class to make your background 2 shades darker on hover. | My red background uses darken-bg-hover-2! |
.darken-bg-hover-3 |
Add this class to make your background 3 shades darker on hover. | My red background uses darken-bg-hover-3! |
Active Shades
Further fine-tune the color of your background when clicked by adjusting its shade.
| Active Shades | ||
|
To change the shade of your colored background when clicked, use the |
||
.lighten-bg-active-3 |
Add this class to make your background 3 shades lighter when clicked. | My red background uses lighten-bg-active-3! |
.lighten-bg-active-2 |
Add this class to make your background 2 shades lighter when clicked. | My red background uses lighten-bg-active-2! |
.lighten-bg-active-1 |
Add this class to make your background 1 shade lighter when clicked. | My red background uses lighten-bg-active-1! |
| Base Color | This is a default background using .bg-hover-red for reference. |
I'm the default red background! |
.darken-bg-active-1 |
Add this class to make your background 1 shade darker when clicked. | My red background uses darken-bg-active-1! |
.darken-bg-active-2 |
Add this class to make your background 2 shades darker when clicked. | My red background uses darken-bg-active-2! |
.darken-bg-active-3 |
Add this class to make your background 3 shades darker when clicked. | My red background uses darken-bg-active-3! |


React is a declarative, component-based Javascript library for building user interfaces.
AngularJS (commonly reffered to as AngularJS 1.X) is a JavaScript framework for building SPAs with an MVC architecture.
AngularJS (commonly reffered to as AngularJS 1.X) is a JavaScript framework for building SPAs with an MVC architecture.
AngularJS (commonly reffered to as AngularJS 1.X) is a JavaScript framework for building SPAs with an MVC architecture.
Polymer is an open-source JavaScript library for building web applications using Web Components.
Ruby on Rails, or Rails, is a server-side web application framework written in Ruby. Rails is an MVC framework, providing default structures for a database, a web service, and web pages.
Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine. Uses an event-driven, non-blocking I/O model taht makes it lightweight and efficient.
ASP.NET Core is the next generation of ASP.NET. It is a modular framework that runs on both the full .NET Framework, on Windows, and the cross-platform .NET Core.
Django (/ˈdʒæŋɡoʊ/ JANG-goh)[5] is a free and open-source web framework, written in Python, which follows the model-view-template (MVT) architectural pattern.


Ryuuganime
Explore
Feedback
Wiki
About
Welcome to Ryuuganime Zen!
The new looks of Ryuuganime.
What's the differences between legacy and upcoming edition of Ryuuganime?
Flexibility on localization
Noice
design but also lightweight
Ready to be an animanga social platforms


Products
Video Intro
Price's
Do you want to know more? Type your email to subscribe
Tank SUV part1
Tank SUV part2
Tank SUV part3
Mackbook Pro 02
$1,800
Lorem ipsum.
Lorem dolor.
Lorem ipsum dolor.
Macbook Air
$1,000
Lorem ipsum.
Lorem dolor.
Lorem ipsum dolor.
Macbook Air-Version2
$1,200
Lorem ipsum.
Lorem dolor.
Lorem ipsum dolor.


{{leg.departure.name}} to {{leg.arrival.name}}
Reservations are not possible for this part of your journey.
Seat reservation is optional for this journey
You must reserve a seat for this (part of the) journey.
{{coach.description}}
You’re booked on this train - You can sit in any vacant seat for your class of travel


Jingle bells, jingle bells,
jingle all the day
I just can’t wait �til Christmas time,
when I can roll �em in the hay
Easy come, easy go
Have a good time with lots of dough
Slippin’ up high, slippin’ down low
Love ‘em and leave ‘em, on with the show
I like female form in minimum dress
Money to spend with a capital “S”
Get a date with the woman in red
Wanna be in heaven with three in a bed
He got it, I want it
They got it, I can’t have it
But I want it, but it don’t matter
She got it and I can’t get it
I want a mistress for Christmas
I want a mistress for Christmas
I want a mistress for Christmas
Easy come, easy go
Slippin’ high, slippin’ low
He got it, I want it
They got it, I can’t have it
I want it, don’t matter
She got it, and I can’t get it
He got it and I want it
They got it and I can’t have it
But I want it, it don’t matter
She got it and I can’t get it
Mistress for Christmas,
you know what I’m talking about
Mistress for Christmas,
they’re gonna send me down, send me down
Mistress for Christmas,
I want the woman in red
at the bottom of my bed
Mistress for Christmas
I can hear you coming down
my snow stick
I wanna ride on your reindeer,
honey, and ring the bells


Dynamic code analysis with Vulture
June 27, 2018
This is a follow up post of Why use coverage to find which parts of a python code were executed? - there we discussed how we stumbled on this plan of dynamic code analysis with vulture. Here, we talk about the development process we (the Vulture team) underwent to integrate Vulture with coverage.py in order to automatically generate a whitelist of functions which Vulture reports as unused but are actually being used.
Overview
The idea was to let coverage do the dynamic analysis and report it’s
results to Vulture (through XML
) which could then be used to cross check
functions being reported as unused by Vulture. It was further decided to present
this functionality to user in the form of a command line flag, eg.:
vulture --make-whitelist coverage.xml files/
This would print a whitelist containing false positives reported for files/
to
stdout
. Let’s walk through all of it step by step:
Dynamic Code Analysis - What is it?
To analyse a program dynamically means to execute the program on a real or virtual processor and to monitor the process to check which lines are being hit (i.e. being used). This is in contrast to static analysis where the program is analysed on the sole basis of source code or some form of code object.
coverage.py is a tool, widely popular in Python community which allows user to perform code coverage measurements through dynamic code analysis.
Implementing –make-whitelist
Code was pretty simple - just look up for hit
switch in the XML
in the
entire range of the unused function. As soon as you find any line which is used,
print it. ;-)
Here is the make_whitelist
module from vulture:
# vulture/make_whitelist.py
from __future__ import print_function
from collections import defaultdict
import os.path
from xml.etree import ElementTree as ET
from vulture import utils
def create_namewise_dict(v):
namewise_unused_funcs = defaultdict(lambda: [])
for item in v.unused_funcs:
filename = os.path.normcase(utils.format_path(item.filename))
namewise_unused_funcs[filename].append(item)
return namewise_unused_funcs
def make_whitelist(v, xml):
xpath_file = './packages/package/classes/class'
with open(xml) as f:
tree = ET.parse(f)
files = [node.attrib['filename'] for node in tree.findall(xpath_file)]
namewise_unused_funcs = create_namewise_dict(v)
for filename in files:
xpath = ('./packages/package/classes/class/[@filename="{}"]'
'/lines/line[@hits="1"]'.format(filename))
lines_hit = [int(
node.attrib['number']) for node in tree.findall(xpath)]
filename = os.path.normcase(filename)
unused_funcs = namewise_unused_funcs.get(filename, [])
if unused_funcs:
print("# " + filename)
for item in unused_funcs:
span = item.first_lineno+1, item.last_lineno+1
for lineno in range(*span):
if lineno in lines_hit:
print(item.name)
break
print()
Were there any problems?
Yes, a lot of them. But, I’m glad that there are a lot of smart people in the Vulture community. ;-)
Here are some weird & notable issues I would like to document:
Output all over pytest results
When writing tests, I had to capture the output when running make_whitelist
,
so I decided to use pytest’s capsys fixture. The code was as follows:
def test_create_whitelist(v, tmpdir, capsys):
code = """\
class Greeter:
def greet(self):
print("Hi")
greeter = Greeter()
greet_func = getattr(greeter, "greet")
greet_func()
"""
expected_output = """\
# {}
greet
"""
sample = os.path.normcase(str(tmpdir.join("unused_code.py")))
xml = str(tmpdir.join("coverage.xml"))
with open(sample, 'w') as f:
f.write(code)
subprocess.call(["coverage", "run", sample])
subprocess.call(["coverage", "xml", "-o", xml])
v.scavenge([sample])
make_whitelist(v, xml)
assert capsys.readouterr().out == expected_output.format(sample)
But, the output from coverage
and scavenge
(in verbose mode) would pollute
capsys.readouterr().out
, so I tried disabling capsys from recording while
executing these commmands, therefore tried this:
# ...
with capsys.disabled():
subprocess.call(["coverage", "run", sample])
subprocess.call(["coverage", "xml", "-o", xml])
v.scavenge([sample])
make_whitelist(v, xml)
assert capsys.readouterr().out == expected_output.format(sample)
The tests now passed, \o/
, but the output we just omitted would now show up
while running the tests, thus ruining pytest’s output when running tests, just
like this:
============================= test session starts ==============================
platform linux -- Python 3.5.5, pytest-3.6.2, py-1.5.3, pluggy-0.6.0
rootdir: /home/travis/build/RJ722/vulture, inifile: setup.cfg
plugins: cov-2.5.1
collected 156 items
tests/test_conditions.py .............. [ 8%]
tests/test_confidence.py ....... [ 13%]
tests/test_errors.py .... [ 16%]
tests/test_format_strings.py ...... [ 19%]
tests/test_imports.py ............. [ 28%]
tests/test_item.py . [ 28%]
tests/test_make_whitelist.py Hi
Scanning: /tmp/pytest-of-travis/pytest-0/test_create_whitelist0/unused_code.py
1 Module(body=[ClassDef(name='Greeter', bases=[], keywords=[], body=[FunctionDef(name='greet', args=arguments(args=[arg(arg='self',
etc...
etc...
1 Load() class Greeter:
. [ 29%]
tests/test_scavenging.py ........................................... [ 57%]
tests/test_script.py ........... [ 64%]
tests/test_size.py .............................. [ 83%]
tests/test_sorting.py . [ 83%]
tests/test_unreachable.py ......................... [100%]
Now, after scratching my head for a while, when I was on the brink of giving up,
I pinged Grand Master The-Compiler for help I think that I underrepresented the enthusiasm and humility
with which Florian helped me. He even asked me to ask for help
sooner rather than later to prevent confusion. A huge shoutout to him - Thank You
so much! . In a matter of seconds, he inspected the code and the output and
pointed out that whenever capsys.disabled()
is used, the output is printed to
stdout
immediately. Aha!
He suggested the following:
# ...
subprocess.call(["coverage", "run", sample])
subprocess.call(["coverage", "xml", "-o", xml])
v.scavenge([sample])
capsys.readouterr() # Flush output from coverage run
make_whitelist(v, xml)
assert capsys.readouterr().out == expected_output.format(sample)
Hooray! \o/
Thank You Florian! :-)
How to pass around fixtures?
Observing the test case, it came to me that most of the code could be reused and thereby I decided to write a helper function and soon came up with the following implementation:
def check_whitelist(code, expected_output, v, tmpdir, capsys):
sample = os.path.normcase(str(tmpdir.join("unused_code.py")))
xml = str(tmpdir.join("coverage.xml"))
with open(sample, 'w') as f:
f.write(code)
subprocess.call(["coverage", "run", sample])
subprocess.call(["coverage", "xml", "-o", xml])
v.scavenge([sample])
capsys.readouterr() # Flush output from coverage run
make_whitelist(v, xml)
assert capsys.readouterr().out == expected_output.format(sample)
def test_create_whitelist(v, tmpdir, capsys):
code = """\
class Greeter:
def greet(self):
print("Hi")
greeter = Greeter()
greet_func = getattr(greeter, "greet")
greet_func()
"""
expected_output = """\
# {}
greet
"""
check_whitelist(code, expected_output, v, tmpdir, capsys)
The problem with this implementation was that with every test case, all the
fixture objects (v
, tmpdir
, capsys
, etc.) needed to be juggled around to
the helper function - there had to be a better way, I thought and started
digging things around but soon, I was down the rabbit hole.
Once again, I went to The-Compiler for rescue - He said that this problem was not uncommon and pointed me to check out the following solutions:
- Creating a class for test cases - Particularly helpful when having a lot of test cases. eg. qutebrowser/qutebrowser/tests/unit/javascript/conftest.py
- Defining an inner function inside a fixture, and then using that fixture instead of calling the function directly. eg. qutebrowser/qutebrowser/tests/unit/browser/webkit/network/test_filescheme.py#L125-L153
Since the former option “looked” like a lot of work, I decided to go with the inner function and quickly came up with the following:
@pytest.fixture
def check_whitelist(code, expected_output):
def check(v, tmpdir, capsys):
sample = os.path.normcase(str(tmpdir.join("unused_code.py")))
xml = str(tmpdir.join("coverage.xml"))
with open(sample, 'w') as f:
f.write(code)
subprocess.call(["coverage", "run", sample])
subprocess.call(["coverage", "xml", "-o", xml])
v.scavenge([sample])
capsys.readouterr() # Flush output from coverage run
make_whitelist(v, xml)
assert capsys.readouterr().out == expected_output.format(sample)
return check
def test_create_whitelist(check_whitelist):
code = """\
class Greeter:
def greet(self):
print("Hi")
greeter = Greeter()
greet_func = getattr(greeter, "greet")
greet_func()
"""
expected_output = """\
# {}
greet
"""
check_whitelist(code, expected_output)
and soon the tests were green and I was busy finding a bottle of Champagne for celebrations when I receive a message from The-Compiler saying that it isn’t supposed to work that way, did it do the job? and myself while being drunk in the divine green flavours of travis replied: “It did :-p”. Next, he tells me that the test running successfully was a false positive - Behind the hoods, it wasn’t running at all. :-(
Due to the way, pytest’s fixtures work, check_whitelist
- the argument to
test_create_whitelist
wasn’t the function check_whitelist
declared outside
and that it was a mere representation and when calling it from within the test,
pytest would intelligently call the inner function. Let’s see the final code:
@pytest.fixture
def check_whitelist(v, tmpdir, capsys):
def check(code, expected_output):
sample = os.path.normcase(str(tmpdir.join("unused_code.py")))
xml = str(tmpdir.join("coverage.xml"))
with open(sample, 'w') as f:
f.write(code)
subprocess.call(["coverage", "run", sample])
subprocess.call(["coverage", "xml", "-o", xml])
v.scavenge([sample])
capsys.readouterr() # Flush output from coverage run
make_whitelist(v, xml)
assert capsys.readouterr().out == expected_output.format(sample)
return check
def test_create_whitelist(check_whitelist):
code = """\
class Greeter:
def greet(self):
print("Hi")
greeter = Greeter()
greet_func = getattr(greeter, "greet")
greet_func()
"""
expected_output = """\
# {}
greet
"""
check_whitelist(code, expected_output)
Despite being deceptive at first (especially given the mismatch in the arguments
and parameters to check_whitelist
), the resulting test case still provides a
neat and robust hack.
Again, Thank You so much Florian! :-)
MS Windows
As usual, Microsoft Windows was being a pain in the ass - which in the end (after 6 hours of swearing and 44 appveyor builds - I do not have access to a Windows machine) was a result of non normalised (wrong slashes and case sensitive) paths, as usual. :-p
At one point, I was thinking of dropping support for Windows, but thanks to Jendrik - I could finally find my way out.


Unit 1: The Principles of marketing research
As you can see, marketing research is very like conducting clinical research!
Image courtesy of ddpavumba / FreeDigitalPhotos.net
The limitations of marketing research also have a great deal in common with clinical research. They include:
Image courtesy of jannoon028 / FreeDigitalPhotos.net
Identify the key characteristics for each of the following examples of pharmaceutical marketing research.
Are they:


The "struts-logic" tag library contains tags that are useful in managing conditional generation of output text, looping over object collections for repetitive generation of output text, and application flow management
The Logic library supplies tags that are useful for manipulating presentation logic without the use of scriptlets.
The functionality of the logic tags can be divided into four groups:
Value Comparisions - The purpose of these tags is to print out the body of the tag if the comparision evaluates to true.
Substring Matching - The purpose of these tags is to match substrings inside of other Strings
Presentation Location - The purpose of these tags is to change the location of the presentation page
Collection Utilities -The purpose of these tags is to handle Collections
Each of the four groups of logic tags have a common set of attributes associated with them. :
Value Comparisions (equal, notEqual, greaterEqual, lessEqual, greaterThan, lessThan, present, notPresent)
Each of the value comparision tags takes a value and compares it to the value of a comparision attribute. If the value given can be successfully converted to a float or double, then a number comparision is performed on the value given and the value of the comparision attribute. Otherwise a String comparision is performed. You have to specify one of the comparision attributes: cookie, header, parameter, property or name. For each of the examples, the tag "someComparisionTag"can be replaced by any of the value comparision tags.
- value - the value to which this tag is going to compare, used in conjunction with one of the comparision attributes: cookie, header, parameter, and property and/or name.
- cookie - the name of the cookie to compare to value
- example:
<logic:someComparisionTag value="someUserName" cookie="userName"> User Logged In </logic:someComparisionTag>- header - the name of the HTTP header to compare to value
- example:
<logic:someComparisionTag value="en_US" header="Accept-Language"> Welcome English-speaking User* </logic:someComparisionTag>*Note: See the section in the user's guide on Internationalized Messages to do things like this better.
- name - the variable to be compared to value is the JSP bean specified by this attribute, if property is not specified, or the value of the specified property of this bean, if property is specified.
- example:
<% String testString = "pantalones"; pageContext.setAttribute("testString", testString, PageContext.PAGE_SCOPE); %> <jsp:useBean id="testString" scope="page" type="java.lang.String" /> <logic:someComparisionTag name="testString" value="pantalones"> Usted tiene pantalones! </logic:someComparision>- parameter - the name of the request parameter to compare to value
- example:
<logic:someComparisionTag value="" parameter="username"> Error: a username must be specified </logic:someComparisionTag>- property - the variable to be compared with value is the property (of the bean specified by the name attribute) specified by this attribute. The property reference can be simple, nested, and/or indexed. property is used in conjunction with name to specify a property in the bean specified by name. For the type of syntax used for property, see the users guide on the Bean Tags.
- scope - the bean scope within which to search for the bean named by the name property, or "any scope" if not specified. Possible values are "page", "request", "session", "application", or "any scope"
Substring Matching (match, notMatch)
The substring matching tags take all the same arguments as the value comparision tags. You compare the String specified by value to any of the comparision values you give it, specified by cookie, header, parameter, property or name. Note that in the examples, matchTag corresponds either the match or notMatch tag. Matching tags also have an additional location attribute added:
- location - has two possible values, "start" and "end". If "start", the substring is attempted to be matched at the beginning of the String, if "end", then the substring is attempted to be matched to the end of the String
- example:
<logic:matchTag parameter="action" value="processLogin"> Processing Login.... </logic:matchTag> Basically, in this short example, a request parameter "action" was compared to see if it was equal to the String value "processLogin". In this case, matchTag would have to be <logic:match>.Presentation Location (forward, redirect)
The redirect tag is resposible for sending a re-direct to the client's browser, complete with URL-rewriting if it's supported by the container. Its attributes are consistent with the Struts HTML
link
tag. The base URL is calculated based on which of the following attributes you specify (you must specify exactly one of them):
- forward - Use the value of this attribute as the name of a global ActionForward to be looked up, and use the context-relative URI found there.
- href - Use the value of this attribute unchanged.
- page - Use the value of this attribute as a context-relative URI, and generate a server-relative URI by including the context path.
The forward tag is responsible for either redirecting or forwarding to a specified global action forward. To define a global ActionForward, see The Action Mappings Configuration File. You can specify whether the forward re-directs or forwards when executed in the config file. The forward tag has one attribute:
- name - The logical name of the ActionForward to use
Collection Utilities (iterate)
The iterate tag is responsible for executing it's body content once for every element inside of the specified Collection. There is one required attribute:
- id - The name of a page scope JSP bean that will contain the current element of the collection on each iteration
The other attributes allow for more flexibility on which Collection to iterate and how to do it:
- collection - a runtime expression that evaluates to a Collection to be iterated
- example:
<% java.util.Vector vector = new java.util.Vector(); vector.add(new Integer(12)); vector.add(new Integer(5)) %><bean:iterate id="myCollectionElement" collection="<% vector %>"> Do something with myCollectionElement </bean:iterate>
- length - The maximum number of entries (from the underlying collection) to be iterated through on this page. This can be either an integer that directly expresses the desired value, or the name of a JSP bean (in any scope) of type java.lang.Integer that defines the desired value. If not present, there will be no limit on the number of iterations performed
- name - The name of the JSP bean containing the collection to be iterated (if property is not specified), or the JSP bean whose property getter returns the collection to be iterated (if property is specified).
- example:
<%
java.util.ArrayList list = new java.util.ArrayList(); list.add("First"); list.add("Second"); list.add("Third"); list.add("Fourth"); list.add("Fifth"); pageContext.setAttribute("list", list, PageContext.PAGE_SCOPE); %> <logic:iterate id="myCollectionElement" name="list"> Do something with myCollectionElement </logic:iterate>- offset - The zero-relative index of the starting point at which entries from the underlying collection will be iterated through. This can be either an integer that directly expresses the desired value, or the name of a JSP bean (in any scope) of type java.lang.Integer that defines the desired value. If not present, zero is assumed (meaning that the collection will be iterated from the beginning.
- property - Name of the property, of the JSP bean specified by name, whose getter returns the collection to be iterated. See the user's guide for the bean tag library for the syntax of the property attribute
- scope - The bean scope within which to search for the bean named by the name property, or "any scope" if not specified. Possible values are "page", "request", "session", "application", or "any scope"
- type - Fully qualified Java class name of the element to be exposed through the JSP bean named from the id attribute. If not present, no type conversions will be performed. NOTE: The actual elements of the collection must be assignment-compatible with this class, or a request time ClassCastException will occur.
- example:
<% java.util.ArrayList list = new java.util.ArrayList(); list.add("First"); list.add("Second"); list.add("Third"); list.add("Fourth"); list.add("Fifth"); pageContext.setAttribute("list", list, PageContext.PAGE_SCOPE); %> <logic:iterate id="myCollectionElement" name="list" type="java.lang.String"> Do something with myCollectionElement </logic:iterate>
Value Comparisions
Logic Equivalence Tags (equal, notEqual, greaterEqual, lessEqual, lessThan, greaterThan)
You can compare these tags to the "==", "!=" ,">=", "<=", "<", and ">"logic operators in most languages. Their usage is fairly straightforward for numbers. For an example, we'll create a small "Guess That Number" game that uses request parameters from a form input to play. The number will be hardcoded as "7", because this is just an example. Note that this is actually putting application logic inside of jsp pages, and isn't the recommended development method for Struts. It's just an easy way to show how these tags are used:
The first step is to develop the form that will call on the processing jsp page. This form will use the "GET" method so that you can see the request parameter in the URL. The POST method can also be used with no problem or changes.
[numberGuess.jsp]
<form action="numberProcess.jsp" method="GET"> Please Enter a Number From 1-10: <input type="text" name="number" />
  <input type="submit" name="Guess Number" />  </form>The next step is to create the processing page. It uses the struts-logic taglib. For information on how to set this tag library up in your application to use, see The Web Application Deployment Descriptor[numberProcess.jsp]
<%@ page language="java" %> <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %> <logic:equal parameter="number" value="7"> You guessed right! You win a high speed blender! </logic:equal> <logic:notEqual parameter="number" value="7">  <logic:lessThan parameter="number" value="7"> A little higher... </logic:lessThan>  <logic:greaterThan parameter="number" value="7"> A little lower... </logic:greaterThan> </logic:notEqual>Basically, the numberProcess.jsp page uses the equal tag to check if the guess is 7, and if so, prints out a congratulatory message. If the number isn't equal, specified by the use of the <logic:notEqual> tag, it uses the greaterThan and lessThan tags to check if the number is higher or lower than 7, and prints out a hint. As said before, this is a horribly designed small application, with no validity checks on the number input, but shows the basic usage of the logic equal tags
For String comparisions, the equal tags use the java.lang.String.compareTo() method. See the javadocs on the compareTo() method for more information, located here.
Match and Present Tags (match, notMatch, present, notPresent)
You use the match tags in conjunction with the present tags in order to do substring matches. For an example using this we'll use headers, specifically the "Referer" header. The HTTP referer header gives the URL of the document that refers to the requested URL. We'll use this to check if the user is coming from a link specified by a Google search, and offer a personalized greeting, frightening users that find our site through the search engine with our amazing intimate knowledge of their browsing habits:
[sneaky.jsp]
<%@ page language="java" %> <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>  <logic:present header="Referer"> <logic:match header="Referer" value="google.com"> I see you found our site through Google... interesting. </logic:match> <logic:notMatch header="Referer" value="google.com"> Welcome to the site, we're secretly logging what site you came from, because we're shady... </logic:notMatch> </logic:present>  <logic:notPresent header="Referer"> Hi, welcome to our site. Please fill out our Form and tell us where you're coming from. </logic:notPresent>Note: Another interesting usage of these tags and headers would be to use the "User-Agent" header to display browser-specific javascript.
Collection Utilities (iterate)
For an example of using the <logic:iterate> tag, we'll use one of the previous examples given, in it's entirety. This example uses the <bean:write> tag from the Bean Tag Library, see the User's Guide on the bean tag library for more information on it's usage:
[iterate.jsp]
<%@ page language="java" %> <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %><% java.util.ArrayList list = new java.util.ArrayList(); list.add("First"); list.add("Second"); list.add("Third"); list.add("Fourth"); list.add("Fifth"); pageContext.setAttribute("list", list, PageContext.PAGE_SCOPE); %> <logic:iterate id="myCollectionElement" name="list"> Element Value: <bean:write name="myCollectionElement" />
 </logic:iterate>


I like hiking, play volleyball, puppies, and my favorite color...is light tan.
Rose enjoys many things
My contact info is www.youknowyouloverose.com Visit Facebook.com!


Your organisation
Business Organisation
If this is not the correct organisation email the application lead
Please note, if you are representing a different organisation then you will need to make a new account.
ContinueIf this is not the correct organisation email the application lead
Please note, if you are representing a different organisation then you will need to make a new account.
Continue


These control the amount of waveshaper width modulation. The displayed values are the percentage width variation per {_unit} of modulation, if the "saws" or "pulse" shape is selected, or the number of cycles of FM per unit of modulation if one of the "FM" shapes are selected. This has no effect for a "noise" or "impulse" shape is selected.
These are contained in the {Waveshaper_mod_cluster Waveshaper mod clusters} within the {Waveshaper_section}.
These are contained in the WIDTH section of the right panel, under the following parameter numbers:
| mod 1 | mod 2 | |
| {sw-36.png height=48} | {sw-set-split.png height=48} {sw-36.png height=48} |
These appear in the display as Wave Mod1-2 Depth.
These are accessed via the following {_NRPN NRPNs}:
| mod 1 | mod 2 | ||
| A | 1,51 | 1,53 | |
| B | 2,51 | 2,43 |
Since these are {_bipolar} parameters, the values are offset by 64.
The values are displayed as percentages or cycles:
| MIDI | percent | cycles | ||
| 0 | \-100% | \-16cyc | ||
| \b\n\b\n\b | \b\n\b\n\b | \b\n\b\n\b | ||
| 64 | off | off | (default) | |
| \b\n\b\n\b | \b\n\b\n\b | \b\n\b\n\b | ||
| 127 | +100% | +16cyc |


This is a Template
1
2
1
with linebreaks
note the heigth on the right
with linebreaks
note the heigth on the right
2
This element has width 60%
This element has width 80%
2
This element has width 50%
2
This element has width 50% but no line breaks.
Feel free to change your browser window size
to see how this text adjust itself
2
3